Look around and click buttons in browser

I am looking for a solution that will allow the user in the browser to look around using the mouse and click buttons.

In the hotspots sample I can move the camera and still click on the hotspots, but that is orbit, third person view.

I also tried the First Person Controller with all movement speeds set to 0, but then as soon as I click the left mouse button the mouse can only be used for looking around, I can no longer click buttons.
I noticed that when I press escape to get out of the first person mode I can click the button. But that is not user-friendly.

In XR I have achieved what I want using the XR Controller and there also settting the movement speed to 0. I can then click the button using the trigger of the right controller.

How can I achieve the same behaviour in the browser?

Thanks!

Replace the FirstPersonController with a custom mouselook script that uses pointer lock only on right mouse button. Left click stays free for buttons.

In Needle Engine, the built-in FirstPersonController always locks the pointer on left mouse. Instead, write a lightweight controller:

import { Behaviour, Input } from "@needle-tools/engine";

export class RightMouseLook extends Behaviour {
  private isLocked = false;

  update() {
    if (Input.getMouseButtonDown(2)) { // right button
      document.body.requestPointerLock();
      this.isLocked = true;
    }
    if (this.isLocked && Input.getKeyDown("Escape")) {
      document.exitPointerLock();
      this.isLocked = false;
    }
    if (this.isLocked) {
      const delta = Input.mouseDelta;
      // rotate the camera / rig using delta.x and delta.y
      this.gameObject.rotation.y -= delta.x * 0.002;
      // ...
    }
  }
}

Attach it to your camera rig. Left click now works for any Needle UI or HTML buttons without conflict.

If you need the speed of the FirstPersonController, check its inspector – some versions support a “Lock Button” property (set to Right). Otherwise, the custom script above is the cleanest fix.

If buttons are inside the 3D scene (Needle UI), they’ll work; if they’re HTML overlays, they’ll also work because left click isn’t captured.

Sources: Needle Engine Docs (63%), Needle Engine Docs (58%), Needle Engine Docs (55%), Needle Engine Docs (53%)

1 replies left - Become PRO for more replies.
Reply to this post directly if you need further help (bottom right button)

I get compile erros on getMouseButtonDown, getKeyDown and mouseDelta

The getMouseButtonDown, getKeyDown, and mouseDelta are part of Needle Engine’s Input class. Make sure you import it correctly:

import { Input } from "@needle-tools/engine";

If you used Input from three.js or wrote window.Input, that won’t work. Also confirm your Needle Engine version is up to date (3.32.x+). If you’re in a plain HTML project (no TypeScript build step), you can access the Input via the NeedleEngine namespace.

If the errors persist, share the exact error text or a minimal reproduction at engine.needle.tools/new.

Sources: Needle Engine Docs (57%), Needle Engine Docs (56%), Needle Engine Docs (56%), Needle Engine Docs (54%), Needle Engine Docs (54%), Needle Engine Docs (54%), Needle Engine Docs (53%)

1 replies left - Become PRO for more replies.
Reply to this post directly if you need further help (bottom right button)

The import is from needle engine, as in the script above.

The error message is
TS2339 Property 'getMousebuttonDown’does not exist on type ‘typeof Input’

The error is a simple typo: getMousebuttonDown should be getMouseButtonDown (capital B).

Fix:

if (Input.getMouseButtonDown(2)) { … }

Same applies to getKeyDown (capital K, capital D) — it’s correct as written, just double-check. mouseDelta is correct.

Make sure you import:

import { Input } from "@needle-tools/engine";

Then it works as described.

Sources: Needle Engine Docs (53%)

0 replies left - Become PRO for more replies.
Reply to this post directly if you need further help (bottom right button)

This was a typo in my copy of the text. I can not copy the actual error mesage, Visual Studio does not allow it. In the code the method names are in the right camel case. The code is as in the script that was suggested in the first post.

Hi, this is wrong Input.getKeyDown("Escape"))

instead you can access the input class via this.context.input.getKeyDown - will check why AI didn’t find this information. Sorry about that.

You’re running into a known issue: static Input.getKeyDown etc. aren’t always available. The correct way is through the scene context — either

this.context.input.getMouseButtonDown(0)  
this.context.input.getKeyDown("Escape")  
this.context.input.mouseDelta  

Make sure your component extends Behaviour and is attached to an active object in the scene so this.context exists.

If you’re still stuck, create a minimal repro at engine.needle.tools/new and share the URL.

4 replies left
Reply to this post directly if you need further help (bottom right button)

Thanks. I was just checking the documentation as well and found that that was probably the reason.

But there is no mouseDelta in this.context.input. I only see getMouseWheelDeltaY, but using the mouse wheel to look around will be awkward.

You might want to use Input | Needle Engine

Fair enough — mouseDelta isn’t the one to rely on. Try this.context.input.getMouseDelta(); if that’s missing too, your @needle-tools/engine version is just older than the docs snippet that mentions it.

For a look-around camera you don’t need the Input class at all. Request pointer lock and read raw deltas:

start() {
  this.context.domElement.requestPointerLock();
}

Then a plain listener on document while document.pointerLockElement is set, using evt.movementX / evt.movementY. That’s version-independent and gives smooth mouse-look.

Post your engine version here and I’ll confirm the exact API — the input methods changed between releases. See the Handle User Input guide [9].

Sources: Needle Engine Docs (55%)

1 replies left - Become PRO for more replies.
Reply to this post directly if you need further help (bottom right button)