Skip to content

Conversation

@sciecode
Copy link
Contributor

It's becoming fairly common for me to need to modify the hardcoded number of touches for rotate and dollypan. I would imagine others could benefit from having control over that as well.

The only problem with this approach would be when users incorrectly pick a single touch for the dollypan. Perhaps a warning would suffice?

@sciecode
Copy link
Contributor Author

/ping @mrdoob @Mugen87 any feedback on this change?

@WestLangley
Copy link
Collaborator

It's becoming fairly common for me to need to modify the hardcoded number of touches for rotate and dollypan.

What are the values you are using in your app?

@sciecode
Copy link
Contributor Author

What are the values you are using in your app?

First time I modified, I disabled dollypan and set:

  1. custom event
  2. rotate

Second time:

  1. custom event
  2. rotate
  3. dollypan

@WestLangley
Copy link
Collaborator

Your suggestion has merits, but you can't pinch-to-zoom with one finger, and with three fingers it is -- well -- a bit odd. The code relies on two touches for zooming.

I am reluctant to support adding a feature unless it just works, otherwise we get complaints, but as I said, your suggestion is not without merit.

MapControls is also hard-coded as far as the number of touches is concerned. I'd like to keep the two codebases similar. It is easier to maintain that way.

I am on the fence...

@sciecode
Copy link
Contributor Author

sciecode commented Jun 18, 2019

Your suggestion has merits, but you can't pinch-to-zoom with one finger, and with three fingers it is -- well -- a bit odd. The code relies on two touches for zooming.

I completely agree. It is a bit awkward.

The most useful case for this change is definitely being able to remap rotate to two fingers and allow one finger for custom events, to be honest.

Let's see how others feel about it, but I'm not strongly attached to this idea as well.
Promise I won't get mad if changes don't get merged 😄

@Mugen87
Copy link
Collaborator

Mugen87 commented Jun 19, 2019

The most useful case for this change is definitely being able to remap rotate to two fingers and allow one finger for custom events, to be honest.

TBH, I don't think we need an API change for this rather unusual use case. The current touch interaction seems ideal to me and I would not encourage users to change with it a respective interface.

@sciecode
Copy link
Contributor Author

TBH, I don't think we need an API change for this rather unusual use case. The current touch interaction seems ideal to me and I would not encourage users to change with it a respective interface.

I understand why you say that, but I don't think it's that unusual at all.

Some applications might want to have a pan option as a single touch event.
Others might want just to zoom in or out based on a single touch y coordinate (not currently supported)
You might want to set a multitude of custom events and integrate with controls api.

I'm not saying my approach in the PR is the one we should go for. Perhaps, rethinking a more customizable api would be the correct thing to do. I think other approaches are only unusual because we might've gotten used to this fixed scheme, not necessarily because there's no need for other interfaces.

I understand that OrbitControls is still an example file and it's meant to be modified accordingly to the user needs, but I also believe it's as much of a core file as it gets. Likely being the most used example file in the whole library.

So I can see how adapting or rethinking the API could be an advantage in this scenario.

@WestLangley
Copy link
Collaborator

The current touch interaction seems ideal to me and I would not encourage users to change with it a respective interface.

I think @sciecode's use cases are perfectly reasonable -- it is just that the PR proposes an overly-general solution that allows options that do not make sense.

@WestLangley
Copy link
Collaborator

As I have said previously, I am reluctant to support any further changes to OrbitControls -- other than bug fixes.

However, on balance, I think this PR provides a valuable feature. I would request that the change also be applied to MapControls, however.

@sciecode
Copy link
Contributor Author

@Mugen87 @WestLangley thoughts on extending this approach by creating independent zoom and pan functionalities and also displaying error for zoom/dollypan on single touch?

default api would look something like this:

this.touches = { 
    rotate: 1,
    dollypan: 2, // keeps current implementation
    pan: THREE.INACTIVE,
    zoom: THREE.INACTIVE
}

it is just that the PR proposes an overly-general solution that allows options that do not make sense

It still doesn't solve this problem, but given that documentation is clear about it and that we provide a descriptive error on incorrect use. I don't see this being a big problem.

On the plus side, it would allow for much better control over touch behaviors.

@WestLangley
Copy link
Collaborator

@sciecode I prefer your current simple proposal. I wouldn't worry about parameter validation.

@sciecode
Copy link
Contributor Author

sciecode commented Jun 28, 2019

MapControls and OrbitControls are very similar right now.

I don't really see the use of having two classes that fulfill almost the same purpose, when we can adjust one to do both things ( and more ). That will require us to implement touchPan and touchDollyRotate on OrbitControl, but I think this is overall a great improvement over our current scheme.

A different approach to this PR, would be to only allow certain touch actions based on the number of fingers. If an invalid configuration is used, we simply treat it as none. That way we solve the current problem with this PR and also remove the necessity of MapControls.

proposed changes - branch

@WestLangley
Copy link
Collaborator

@sciecode I think this looks reasonable if you could have MapControls extend OrbitControls so it could be retained as an API.

Can you specify some example mouse and touch settings we could try? Don't forget that some users just want to be able to swap left and right mouse buttons.

@sciecode
Copy link
Contributor Author

sciecode commented Jun 30, 2019

@sciecode I think this looks reasonable if you could have MapControls extend OrbitControls so it could be retained as an API.

Can you specify some example mouse and touch settings we could try? Don't forget that some users just want to be able to swap left and right mouse buttons.

On this newly proposed scheme, changing from OrbitControls functionalities to MapControls would be as simple as modifying the following properties:

// mapControls properties

controls.mouseButtons.LEFT = THREE.MOUSE.RIGHT;
controls.mouseButtons.RIGHT = THREE.MOUSE.LEFT;

controls.touches.ONE = THREE.TOUCH.PAN;
controls.touches.TWO = THREE.TOUCH.DOLLY_ROTATE;

MapControls example

disabling either one or two finger events can be achieved this way:

 controls.touches.ONE = undefined;

I made sure to not modify mouse / keyboard controls API in anyway. I'm just altering touch events in both PRs suggestions.

@WestLangley
Copy link
Collaborator

I made sure to not modify mouse / keyboard controls API in anyway. I'm just altering touch events in both PRs suggestions.

We have to fix that, too. It does not appear you are handling ctrlKey/metaKey/shiftKey correctly.

With the following changes to your proposed code, OrbitControls appears to work correctly for mouse events, and also to be backward-compatible:

In constants.js:

// LEFT, MIDDLE, RIGHT will be deprecated in favor of specifying "actions"
export var MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 };

In OrbitControls.js:

// Mouse button actions
this.mouseButtons = { LEFT: THREE.MOUSE.ROTATE, MIDDLE: THREE.MOUSE.DOLLY, RIGHT: THREE.MOUSE.PAN };

//

function onMouseDown( event ) {

	if ( scope.enabled === false ) return;

	// Prevent the browser from scrolling.

	event.preventDefault();

	// Manually set the focus since calling preventDefault above
	// prevents the browser from setting it automatically.

	scope.domElement.focus ? scope.domElement.focus() : window.focus();

	switch ( event.button ) {

		case 0:

			switch ( scope.mouseButtons.LEFT ) {

				case THREE.MOUSE.ROTATE:

					if ( event.ctrlKey || event.metaKey || event.shiftKey ) {

						if ( scope.enablePan === false ) return;

						handleMouseDownPan( event );

						state = STATE.PAN;

					} else {

						if ( scope.enableRotate === false ) return;

						handleMouseDownRotate( event );

						state = STATE.ROTATE;

					}

					break;

				case THREE.MOUSE.PAN:

					if ( scope.enablePan === false ) return;

					handleMouseDownPan( event );

					state = STATE.PAN;

					break;

				default:

					state = STATE.NONE;

			}

			break;


		case 1:

			switch ( scope.mouseButtons.MIDDLE ) {

				case THREE.MOUSE.DOLLY:

					if ( scope.enableZoom === false ) return;

					handleMouseDownDolly( event );

					state = STATE.DOLLY;

					break;


				default:

					state = STATE.NONE;

			}

			break;

		case 2:

			switch ( scope.mouseButtons.RIGHT ) {

				case THREE.MOUSE.ROTATE:

					if ( scope.enableRotate === false ) return;

					handleMouseDownRotate( event );

					state = STATE.ROTATE;

					break;

				case THREE.MOUSE.PAN:

					if ( scope.enablePan === false ) return;

					handleMouseDownPan( event );

					state = STATE.PAN;

					break;

				default:

					state = STATE.NONE;

			}

			break;

	}

	if ( state !== STATE.NONE ) {

		document.addEventListener( 'mousemove', onMouseMove, false );
		document.addEventListener( 'mouseup', onMouseUp, false );

		scope.dispatchEvent( startEvent );

	}

}

@sciecode
Copy link
Contributor Author

I really like this, gonna setup a proper PR with these changes.

// Mouse button actions
this.mouseButtons = { LEFT: THREE.MOUSE.ROTATE, MIDDLE: THREE.MOUSE.DOLLY, RIGHT: THREE.MOUSE.PAN };

I was gonna suggest that we changed mouse constants to match touch pattern 👍
Thanks @WestLangley

@WestLangley
Copy link
Collaborator

If we carry this to its natural completion, MapControls properties would now be:

controls.mouseButtons.LEFT = THREE.MOUSE.PAN;
controls.mouseButtons.RIGHT = THREE.MOUSE.ROTATE;

controls.touches.ONE = THREE.TOUCH.PAN;
controls.touches.TWO = THREE.TOUCH.DOLLY_ROTATE;

@WestLangley
Copy link
Collaborator

You will have to handle ctrlKey/metaKey/shiftKey for the MapControls case, too, but that is straight-forward.

Please do your best to make sure the behavior is not changed. This is a refactoring only.

Consider defining MapControls in the same file to retain the API. I don't particularly care one way or the other, but I expect others will.

@sciecode sciecode closed this Jul 3, 2019
@sciecode sciecode deleted the dev-orbit branch July 3, 2019 01:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants