Skip to content
This repository has been archived by the owner on Jul 22, 2024. It is now read-only.

Introducing FreeFlight fallback #213

Merged
merged 5 commits into from
Apr 3, 2018
Merged

Introducing FreeFlight fallback #213

merged 5 commits into from
Apr 3, 2018

Conversation

delapuente
Copy link
Contributor

@delapuente delapuente commented Mar 23, 2018

Fix #125
I need some feedback. Look at how it behaves on:

  • Desktop supporting WebVR: no fallback is available.
  • Desktop not supporting WebVR: movement and orientation fallbacks are available.
  • Mobile: only movement fallback would be available but the absence of keyboard renders it unusable. I'm planning to address this problem in another bug and provide two-finger navigation of the scene.

Use W, A, S, D or arrow keys to move forward, left, backward or right.
Use R, F to increase or decrease elevation.
Use Q, E to roll to the left or to the right.
Use click and drag to yaw and pitch.

@delapuente delapuente requested review from cvan and caseyyee March 23, 2018 09:47
@delapuente delapuente added this to the v1.2.0 milestone Mar 23, 2018
Copy link
Contributor

@cvan cvan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Desktop not supporting WebVR: movement and orientation fallbacks are available.

first off: fantastic, fantastic work! this works spiffy! and your code handles all the position and orientation cases well 👍👍👍💯💯💯

Desktop supporting WebVR: no fallback is available.

this is confusing to me. I think we should still support the mouse-look controls ("fallback"). see my screenshots earlier in the issue.

when I'm in Chrome on Windows (with no WebVR/OpenVR flags enabled), the free-flight controls work properly and the keybindings too 👍 🎉

when I'm in Firefox on Windows (which has WebVR enabled), before I enter VR, I'd expect to have the same controls. or at a minimum, have the orientation and position in mono mode before I enter VR.

currently, in Firefox on Windows the demo scene seems broken in its current state (what with the default camera position and the scenery).

what are your thoughts on this?

see my screenshots:

Firefox (with WebVR API support)

image
image

Chrome (without WebVR API support)

image
image


Mobile: only movement fallback would be available but the absence of keyboard renders it unusable. I'm planning to address this problem in another bug and provide two-finger navigation of the scene.

awesome! sounds totally reasonable. can you file issues for those?

@@ -288,24 +288,33 @@

return navigator.getVRDisplays().then(function(displays) {
if (!displays.length) {
return null;
showInstruction(document.querySelector('#novr'));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: it can happen in #104, but the showInstruction function could be changed to accept no arguments:

el = document.querySelector('#novr');

if (vrDisplay.capabilities) {
if (vrDisplay.capabilities.canPresent) {
// Enable button to toggle entering/exiting VR.
entervrButton.dataset.enabled = 'true';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: again, this could be a #104 issue: I know you didn't change this, but shouldn't this be set to 'false' (or the data-enabled attribute removed) if !vrDisplay.capabilities || !vrDisplay.capabilities.canPresent?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made a more in-depth refactor here.

if (vrDisplay.capabilities && vrDisplay.capabilities.canPresent) {
// Enable button to toggle entering/exiting VR.
entervrButton.dataset.enabled = 'true';
if (vrDisplay.capabilities) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know it's been a while since we wrote this code, so I can't recall the scenario but do you know the cases in which there wouldn't be a capabilities object on the VRDisplay instance? VRDisplayCapabilities is polyfilled in the WebVR Polyfill.

at least in v1.1, I think if there's a VRDisplay, there's guaranteed to be VRDisplayCapabilities.

long story short: I think we can remove this check.

showInstruction(document.querySelector('#novr'));
}
if (!hasOrientation) {
gameInstance.SendMessage('WebVRCameraSet', 'RequestFallback', 'orientation');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if vrDisplay.capabilities does not exist, this code path won't be reached (see my comment above about removing the if (vrDisplay.capabilities) statement)

m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 683f145ef879be447ba25c1080ac1984, type: 3}
m_Name:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should there be a name?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems to be OK. Unity writes these files. If there was an error, I suppose Unity would complain about it. I don't see any error but if this is a bug, let's report it in a different bug.


float ForwardMovement() {
return TranslationSpeed(GetDirectionFromAxis(
new List<KeyCode> { KeyCode.W, KeyCode.UpArrow },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can these keys be defined as configurable class properties?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know, but do you think there is any significant perf overhead incurred from invoking these function calls and creating these List objects (as opposed to just doing some conditional if statements checking Input.getKey(…) for each)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've removed constructing the constant objects again and again. I don't think the if alternative would improve the performance in a noticeable way.


float SideMovement() {
return TranslationSpeed(GetDirectionFromAxis(
new List<KeyCode> { KeyCode.D, KeyCode.RightArrow },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can these keys be defined as configurable class properties?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice work handling all these various transforms!

I have to admit: D makes me a bit sick heh - is that a standard convention? and for that key? (I don't doubt it; I just am not used to it.)

Copy link
Contributor Author

@delapuente delapuente Mar 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually D means stride-right in FPS games. I'm convinced that Unity users and game players would find it comfortable and natural.

Copy link
Contributor Author

@delapuente delapuente Mar 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the keys are now customizable except for the drag button.

return RotationMovement(QuantifiedDirection(mouseDeltas.y));
}

float RotationMovement(float direction) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this method is helpful (and DRY), but for me it was a little tricky to follow the nested calls to know the calculated values of the pitch, yaw, roll, etc.


bool isRotationEnabled;

bool isTranslationEnabled;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as comments above for isRotationEnabled

float RollMovement() {
return RotationMovement(GetDirectionFromAxis(
new List<KeyCode> { KeyCode.Q },
new List<KeyCode> { KeyCode.E }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

E probably makes me the sickest 🤢heh. I can see how this might be useful in particular scenes. do you think we could have some of these key options disabled by default? (I suppose like the Toggle VR Mode Key key option, we could just assume an empty value means to not respect it?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, this kind of rotation is not very usual and I would prefer to remove it completely following the recommendation on customization.

@cvan
Copy link
Contributor

cvan commented Mar 27, 2018

Desktop not supporting WebVR: movement and orientation fallbacks are available.

oh, btw, in the default scene, the controller hands appear smooshed together at the origin.

image
image

it looks funny 😆but I assume it's a bug/oversight?

@delapuente
Copy link
Contributor Author

What happened to the hands seems like a bug. They should not be displayed unless there are controls.

You can use WASD or the arrow keys to move forward/backwards, to the
left/right. You can also configure all these keys. Click and drag
the mouse to rotate the views.

The fallback mode is enabled according to the capabilities of the VR
device.

In desktop environments with VR, movement and rotation are available
while not presenting.

In mobile environments, movement and rotation are enabled or disabled
according to the capabilities of the device.
@delapuente delapuente requested a review from cvan March 27, 2018 15:03
@delapuente
Copy link
Contributor Author

@cvan take another look. The RequestFallback API is gone. Now we send the capabilities to Unity so the developer can decide what to do. Actually, the free-flight camera is not special in any way and it can illustrate how to create a non-VR camera for when VR is not available.

I've removed the capability of rolling and added customization options for all the keys moving the camera. Rotation is mouse/touch-screen only.

currently, in Firefox on Windows the demo scene seems broken in its current state (what with the default camera position and the scenery).

This is tricky and it is related to #184. I would provide a "default-height-for-when-no-vr" component in a different component. I can draft one tomorrow. What do you think?

Copy link
Contributor

@cvan cvan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looking real good! awesome improvements, and thanks for addressing everything!

return direction * rotationSpeed * Time.deltaTime;
}

float DirectionFromMovement(float number, float threshold=0.001f) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you don't think this should be configurable? probably fine, eh

if (number < -threshold) {
return -1;
}
return 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, I did - is this convention?

}

void RegisterMouseMovement() {
bool stoppedTracking = Input.GetMouseButtonUp(0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO "Tracking" is a weird word to use because of VR "positional tracking"

can't think of the best word: stoppedMouseDrag, mouseDragReleased, mouseClickReleased?

}

void Update() {
if (translationEnabled) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perfect, thanks!


public class FreeFlightController : MonoBehaviour {

[Tooltip("Enable/disable rotation control.")]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for moving all the public properties and adding the tooltip text labels. they're very helpful (for me definitely anyway)

return 0;
}

bool SomeIsPressed(List<KeyCode> keys) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you rename this to AnyKeyIsPressed or AnyKeyPressed (basically just include the word Key somewhere in this name)?

return keys.FindAll(k => Input.GetKey(k)).Count > 0;
}

void RegisterMouseMovement() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps I missed it in a comment, but did you look into using the Unity MonoBehaviour's onMouseDrag?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the documentation:

OnMouseDrag is called when the user has clicked on a GUIElement or Collider and is still holding down the mouse.

Similar to what happened with the event systems, this is intended for interacting with things that are draggable and not as a generic way of detecting dragging on the screen.

using System.Runtime.InteropServices;
public class WebUI {

[DllImport("__Internal")]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no biggie, really, just FYI: the .meta files use two soft spaces 😄

@@ -1 +1 @@
m_EditorVersion: 2017.3.0f3
m_EditorVersion: 2017.3.1f1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

want to do in separate commit? or are you fine having this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I will commit this directly to master.

@@ -130,6 +130,7 @@ a:link, a:visited {
position: absolute;
top: 0;
width: 100%;
pointer-events: none;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed this - thanks for fixing this 👍 😄

@delapuente delapuente requested a review from cvan March 28, 2018 07:26
@delapuente
Copy link
Contributor Author

I've managed to add a fixing offset for when there is no position capability or we are in a desktop-like environment. I've also changed the components to the main camera since to fix a couple of edge cases and cleaning some things from bug #159 that interfered with this implementation. @cvan feel free to take another look. Remember I won't be available this week.

Copy link
Contributor

@cvan cvan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks again. this looks almost perfect. great work!

just see my comments in RegisterMouseMovement about the mouse-look controls not feeling right (stuttery)

testTimeStart = null;
return;
}
// This way of passing messages is deprecated. Use rich objects instead.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a TODO?


if (displays.length) {
vrDisplay = displays[displays.length - 1];
canPresent = vrDisplay.capabilities.canPresent;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps might be easier to just manage 1 variable called capabilities than the 4 intermediate variables?

}
gameInstance.SendMessage(
'WebVRCameraSet', 'OnVRCapabilities',
JSON.stringify({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we not just JSON.stringify(vrDisplay.capabilities)?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can handle in #104

},

ShowPanel: function (panelId) {
document.dispatchEvent(new CustomEvent('Unity', {detail: {type:'ShowPanel', panelId: Pointer_stringify(panelId)}}));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: space after type:

public float translationSpeed = 7;

[Tooltip("Minimum distance the mouse must move to start registering movement.")]
public float rotationDeadDistance = 0.001f;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks 😄

/// Enables rotation and translation control for desktop environments.
/// For mobile environments, it enables rotation or translation according to
/// the device capabilities.
void EnableAccordingToPlatform() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ahh, okay makes more sense. thanks for the explanation (and filing the follow-up issue) 👍

@@ -260,7 +260,7 @@ PlayerSettings:
m_BuildTargetGraphicsAPIs: []
m_BuildTargetVRSettings:
- m_BuildTarget: Standalone
m_Enabled: 1
m_Enabled: 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good call; we should have this disabled anyway

mouseMovement.Set(0, 0, 0);
}
else if (mouseIsDragging) {
mouseMovement = Input.mousePosition - lastMousePosition;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure if it's coming from the YawMovement or PitchMovement, but the mousedrag (especially at lower regions of the screen) doesn't seem to rotate the camera correctly; it's like a lag or stutter

Copy link
Contributor

@cvan cvan Apr 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

filed issue #219 for enhancement. no worries! no real other concerns I have with the controls; they're totally usable and a huge improvement to the project. thanks again! 👍

@cvan cvan merged commit ec95a92 into MozillaReality:master Apr 3, 2018
@cvan
Copy link
Contributor

cvan commented Apr 3, 2018

thanks! this is sooo good! 🏅

@caseyyee
Copy link
Contributor

caseyyee commented Apr 3, 2018

Nice job @delapuente !
Good one 💯

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants