<!-- Please describe your changes on the following line: --> WebVR API Implementation with HTC Vive support on Windows. The current implementations only enables the WebVR support on Windows. In other platforms the API is available on JavaScript but navigator.vr.getDisplays() returns an empty array. This will change when we add support for more VR providers and platforms ;) Info about the architecture: https://blog.mozvr.com/webvr-servo-architecture-and-latency-optimizations/ --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [ ] These changes fix #__ (github issue number if applicable). <!-- Either: --> - [X] There are tests for these changes OR - [ ] These changes do not require tests because _____ Proprietary openvr.dll must be copied next to servo.exe in order to test on HTC Vive (https://github.com/ValveSoftware/openvr/tree/master/bin/win64) I have added some of the official WebVR samples for testing. Switch on your headset and run: mach run tests/html/webvr/room-scale.html Source-Repo: https://github.com/servo/servo Source-Revision: 518ef39cfd429082dd8dc0d5b13e2db637d08a53
182 lines
5.5 KiB
JavaScript
182 lines
5.5 KiB
JavaScript
// Copyright 2016 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
window.VRSamplesUtil = (function () {
|
|
|
|
"use strict";
|
|
|
|
// Lifted from the WebVR Polyfill
|
|
function isMobile () {
|
|
return /Android/i.test(navigator.userAgent) ||
|
|
/iPhone|iPad|iPod/i.test(navigator.userAgent);
|
|
}
|
|
|
|
function getMessageContainer () {
|
|
var messageContainer = document.getElementById("vr-sample-message-container");
|
|
if (!messageContainer) {
|
|
messageContainer = document.createElement("div");
|
|
messageContainer.id = "vr-sample-message-container";
|
|
messageContainer.style.fontFamily = "sans-serif";
|
|
messageContainer.style.position = "absolute";
|
|
messageContainer.style.zIndex = "999";
|
|
messageContainer.style.left = "0";
|
|
messageContainer.style.top = "0";
|
|
messageContainer.style.right = "0";
|
|
messageContainer.style.margin = "0";
|
|
messageContainer.style.padding = "0";
|
|
messageContainer.align = "center";
|
|
document.body.appendChild(messageContainer);
|
|
}
|
|
return messageContainer;
|
|
}
|
|
|
|
function addMessageElement (message, backgroundColor) {
|
|
var messageElement = document.createElement("div");
|
|
messageElement.classList.add = "vr-sample-message";
|
|
messageElement.style.color = "#FFF";
|
|
messageElement.style.backgroundColor = backgroundColor;
|
|
messageElement.style.borderRadius = "3px";
|
|
messageElement.style.position = "relative";
|
|
messageElement.style.display = "inline-block";
|
|
messageElement.style.margin = "0.5em";
|
|
messageElement.style.padding = "0.75em";
|
|
|
|
messageElement.innerHTML = message;
|
|
|
|
getMessageContainer().appendChild(messageElement);
|
|
|
|
return messageElement;
|
|
}
|
|
|
|
// Makes the given element fade out and remove itself from the DOM after the
|
|
// given timeout.
|
|
function makeToast (element, timeout) {
|
|
element.style.transition = "opacity 0.5s ease-in-out";
|
|
element.style.opacity = "1";
|
|
setTimeout(function () {
|
|
element.style.opacity = "0";
|
|
setTimeout(function () {
|
|
if (element.parentElement)
|
|
element.parentElement.removeChild(element);
|
|
}, 500);
|
|
}, timeout);
|
|
}
|
|
|
|
function addError (message, timeout) {
|
|
var element = addMessageElement("<b>ERROR:</b> " + message, "#D33");
|
|
|
|
if (timeout) {
|
|
makeToast(element, timeout);
|
|
}
|
|
|
|
return element;
|
|
}
|
|
|
|
function addInfo (message, timeout) {
|
|
var element = addMessageElement(message, "#22A");
|
|
|
|
if (timeout) {
|
|
makeToast(element, timeout);
|
|
}
|
|
|
|
return element;
|
|
}
|
|
|
|
function getButtonContainer () {
|
|
var buttonContainer = document.getElementById("vr-sample-button-container");
|
|
if (!buttonContainer) {
|
|
buttonContainer = document.createElement("div");
|
|
buttonContainer.id = "vr-sample-button-container";
|
|
buttonContainer.style.fontFamily = "sans-serif";
|
|
buttonContainer.style.position = "absolute";
|
|
buttonContainer.style.zIndex = "999";
|
|
buttonContainer.style.left = "0";
|
|
buttonContainer.style.bottom = "0";
|
|
buttonContainer.style.right = "0";
|
|
buttonContainer.style.margin = "0";
|
|
buttonContainer.style.padding = "0";
|
|
buttonContainer.align = "right";
|
|
document.body.appendChild(buttonContainer);
|
|
}
|
|
return buttonContainer;
|
|
}
|
|
|
|
function addButtonElement (message, key, icon) {
|
|
var buttonElement = document.createElement("div");
|
|
buttonElement.classList.add = "vr-sample-button";
|
|
buttonElement.style.color = "#FFF";
|
|
buttonElement.style.fontWeight = "bold";
|
|
buttonElement.style.backgroundColor = "#888";
|
|
buttonElement.style.borderRadius = "5px";
|
|
buttonElement.style.border = "3px solid #555";
|
|
buttonElement.style.position = "relative";
|
|
buttonElement.style.display = "inline-block";
|
|
buttonElement.style.margin = "0.5em";
|
|
buttonElement.style.padding = "0.75em";
|
|
buttonElement.style.cursor = "pointer";
|
|
buttonElement.align = "center";
|
|
|
|
if (icon) {
|
|
buttonElement.innerHTML = "<img src='" + icon + "'/><br/>" + message;
|
|
} else {
|
|
buttonElement.innerHTML = message;
|
|
}
|
|
|
|
if (key) {
|
|
var keyElement = document.createElement("span");
|
|
keyElement.classList.add = "vr-sample-button-accelerator";
|
|
keyElement.style.fontSize = "0.75em";
|
|
keyElement.style.fontStyle = "italic";
|
|
keyElement.innerHTML = " (" + key + ")";
|
|
|
|
buttonElement.appendChild(keyElement);
|
|
}
|
|
|
|
getButtonContainer().appendChild(buttonElement);
|
|
|
|
return buttonElement;
|
|
}
|
|
|
|
function addButton (message, key, icon, callback) {
|
|
var keyListener = null;
|
|
if (key) {
|
|
var keyCode = key.charCodeAt(0);
|
|
keyListener = function (event) {
|
|
if (event.keyCode === keyCode) {
|
|
callback(event);
|
|
}
|
|
};
|
|
document.addEventListener("keydown", keyListener, false);
|
|
}
|
|
var element = addButtonElement(message, key, icon);
|
|
element.addEventListener("click", function (event) {
|
|
callback(event);
|
|
event.preventDefault();
|
|
}, false);
|
|
|
|
return {
|
|
element: element,
|
|
keyListener: keyListener
|
|
};
|
|
}
|
|
|
|
function removeButton (button) {
|
|
if (!button)
|
|
return;
|
|
if (button.element.parentElement)
|
|
button.element.parentElement.removeChild(button.element);
|
|
if (button.keyListener)
|
|
document.removeEventListener("keydown", button.keyListener, false);
|
|
}
|
|
|
|
return {
|
|
isMobile: isMobile,
|
|
addError: addError,
|
|
addInfo: addInfo,
|
|
addButton: addButton,
|
|
removeButton: removeButton,
|
|
makeToast: makeToast
|
|
};
|
|
})();
|