mirror of
https://github.com/overte-org/overte.git
synced 2025-08-04 05:23:33 +02:00
Merge branch 'master' into 21249
This commit is contained in:
commit
68901c8af5
41 changed files with 707 additions and 477 deletions
|
@ -17,6 +17,8 @@ Documentation
|
||||||
=========
|
=========
|
||||||
Documentation is available at [docs.highfidelity.com](https://docs.highfidelity.com), if something is missing, please suggest it via a new job on Worklist (add to the hifi-docs project).
|
Documentation is available at [docs.highfidelity.com](https://docs.highfidelity.com), if something is missing, please suggest it via a new job on Worklist (add to the hifi-docs project).
|
||||||
|
|
||||||
|
There is also detailed [documentation on our coding standards](https://wiki.highfidelity.com/wiki/Coding_Standards).
|
||||||
|
|
||||||
Build Instructions
|
Build Instructions
|
||||||
=========
|
=========
|
||||||
All information required to build is found in the [build guide](BUILD.md).
|
All information required to build is found in the [build guide](BUILD.md).
|
||||||
|
|
4
cmake/externals/openvr/CMakeLists.txt
vendored
4
cmake/externals/openvr/CMakeLists.txt
vendored
|
@ -7,8 +7,8 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
||||||
|
|
||||||
ExternalProject_Add(
|
ExternalProject_Add(
|
||||||
${EXTERNAL_NAME}
|
${EXTERNAL_NAME}
|
||||||
URL https://github.com/ValveSoftware/openvr/archive/v1.0.3.zip
|
URL https://github.com/ValveSoftware/openvr/archive/v1.0.6.zip
|
||||||
URL_MD5 b484b12901917cc739e40389583c8b0d
|
URL_MD5 f6892cd3a3078f505d03b4297f5a1951
|
||||||
CONFIGURE_COMMAND ""
|
CONFIGURE_COMMAND ""
|
||||||
BUILD_COMMAND ""
|
BUILD_COMMAND ""
|
||||||
INSTALL_COMMAND ""
|
INSTALL_COMMAND ""
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import QtQuick 2.5
|
import QtQuick 2.5
|
||||||
import QtQuick.Controls 1.2
|
import QtQuick.Controls 1.4
|
||||||
import QtWebChannel 1.0
|
import QtWebChannel 1.0
|
||||||
import QtWebEngine 1.2
|
import QtWebEngine 1.2
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ import "controls"
|
||||||
import "styles" as HifiStyles
|
import "styles" as HifiStyles
|
||||||
import "styles-uit"
|
import "styles-uit"
|
||||||
import "windows"
|
import "windows"
|
||||||
import HFWebEngineProfile 1.0
|
import HFTabletWebEngineProfile 1.0
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
@ -28,34 +28,10 @@ Item {
|
||||||
x: 0
|
x: 0
|
||||||
y: 0
|
y: 0
|
||||||
|
|
||||||
function goBack() {
|
|
||||||
webview.goBack();
|
|
||||||
}
|
|
||||||
|
|
||||||
function goForward() {
|
|
||||||
webview.goForward();
|
|
||||||
}
|
|
||||||
|
|
||||||
function gotoPage(url) {
|
|
||||||
webview.url = url;
|
|
||||||
}
|
|
||||||
|
|
||||||
function setProfile(profile) {
|
function setProfile(profile) {
|
||||||
webview.profile = profile;
|
webview.profile = profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
function reloadPage() {
|
|
||||||
webview.reloadAndBypassCache();
|
|
||||||
webview.setActiveFocusOnPress(true);
|
|
||||||
webview.setEnabled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id:item
|
|
||||||
width: parent.width
|
|
||||||
implicitHeight: parent.height
|
|
||||||
|
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
id: eventBridgeWrapper
|
id: eventBridgeWrapper
|
||||||
WebChannel.id: "eventBridgeWrapper"
|
WebChannel.id: "eventBridgeWrapper"
|
||||||
|
@ -70,9 +46,9 @@ Item {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height : parent.height
|
height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height : parent.height
|
||||||
|
|
||||||
profile: HFWebEngineProfile {
|
profile: HFTabletWebEngineProfile {
|
||||||
id: webviewProfile
|
id: webviewTabletProfile
|
||||||
storageName: "qmlWebEngine"
|
storageName: "qmlTabletWebEngine"
|
||||||
}
|
}
|
||||||
|
|
||||||
property string userScriptUrl: ""
|
property string userScriptUrl: ""
|
||||||
|
@ -113,7 +89,7 @@ Item {
|
||||||
console.log("Web Entity JS message: " + sourceID + " " + lineNumber + " " + message);
|
console.log("Web Entity JS message: " + sourceID + " " + lineNumber + " " + message);
|
||||||
});
|
});
|
||||||
|
|
||||||
webview.profile.httpUserAgent = "Mozilla/5.0 Chrome (HighFidelityInterface";
|
webview.profile.httpUserAgent = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36";
|
||||||
web.address = url;
|
web.address = url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,28 +113,17 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onNavigationRequested: {
|
||||||
|
if (request.navigationType == WebEngineNavigationRequest.LinkClickedNavigation) {
|
||||||
|
pagesModel.append({webUrl: request.url.toString()})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onNewViewRequested: {
|
onNewViewRequested: {
|
||||||
var component = Qt.createComponent("./TabletBrowser.qml");
|
request.openIn(webView);
|
||||||
|
|
||||||
if (component.status != Component.Ready) {
|
|
||||||
if (component.status == Component.Error) {
|
|
||||||
console.log("Error: " + component.errorString());
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var newWindow = component.createObject();
|
|
||||||
newWindow.setProfile(webview.profile);
|
|
||||||
request.openIn(newWindow.webView);
|
|
||||||
newWindow.eventBridge = web.eventBridge;
|
|
||||||
stackRoot.push(newWindow);
|
|
||||||
newWindow.webView.forceActiveFocus();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // item
|
|
||||||
|
|
||||||
|
|
||||||
Keys.onPressed: {
|
Keys.onPressed: {
|
||||||
switch(event.key) {
|
switch(event.key) {
|
||||||
case Qt.Key_L:
|
case Qt.Key_L:
|
||||||
|
@ -171,4 +136,4 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // dialog
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import QtQuick 2.5
|
import QtQuick 2.5
|
||||||
import QtQuick.Controls 1.4
|
import QtQuick.Controls 1.4
|
||||||
import QtWebEngine 1.1
|
import QtWebEngine 1.2
|
||||||
import QtWebChannel 1.0
|
import QtWebChannel 1.0
|
||||||
import "../controls-uit" as HiFiControls
|
import "../controls-uit" as HiFiControls
|
||||||
import "../styles" as HifiStyles
|
import "../styles" as HifiStyles
|
||||||
|
@ -14,17 +14,20 @@ Item {
|
||||||
height: parent.height
|
height: parent.height
|
||||||
property var parentStackItem: null
|
property var parentStackItem: null
|
||||||
property int headerHeight: 38
|
property int headerHeight: 38
|
||||||
property alias url: root.url
|
property string url
|
||||||
property string address: url
|
property string address: url //for compatibility
|
||||||
property alias scriptURL: root.userScriptUrl
|
property string scriptURL
|
||||||
property alias eventBridge: eventBridgeWrapper.eventBridge
|
property alias eventBridge: eventBridgeWrapper.eventBridge
|
||||||
property bool keyboardEnabled: HMD.active
|
property bool keyboardEnabled: HMD.active
|
||||||
property bool keyboardRaised: false
|
property bool keyboardRaised: false
|
||||||
property bool punctuationMode: false
|
property bool punctuationMode: false
|
||||||
property bool isDesktop: false
|
property bool isDesktop: false
|
||||||
property WebEngineView view: root
|
property WebEngineView view: loader.currentView
|
||||||
|
|
||||||
|
|
||||||
|
property int currentPage: -1 // used as a model for repeater
|
||||||
|
property alias pagesModel: pagesModel
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
id: buttons
|
id: buttons
|
||||||
HifiConstants { id: hifi }
|
HifiConstants { id: hifi }
|
||||||
|
@ -37,29 +40,29 @@ Item {
|
||||||
anchors.leftMargin: 8
|
anchors.leftMargin: 8
|
||||||
HiFiGlyphs {
|
HiFiGlyphs {
|
||||||
id: back;
|
id: back;
|
||||||
enabled: true;
|
enabled: currentPage > 0
|
||||||
text: hifi.glyphs.backward
|
text: hifi.glyphs.backward
|
||||||
color: enabled ? hifistyles.colors.text : hifistyles.colors.disabledText
|
color: enabled ? hifistyles.colors.text : hifistyles.colors.disabledText
|
||||||
size: 48
|
size: 48
|
||||||
MouseArea { anchors.fill: parent; onClicked: stackRoot.goBack() }
|
MouseArea { anchors.fill: parent; onClicked: goBack() }
|
||||||
}
|
}
|
||||||
|
|
||||||
HiFiGlyphs {
|
HiFiGlyphs {
|
||||||
id: forward;
|
id: forward;
|
||||||
enabled: stackRoot.currentItem.canGoForward;
|
enabled: currentPage < pagesModel.count - 1
|
||||||
text: hifi.glyphs.forward
|
text: hifi.glyphs.forward
|
||||||
color: enabled ? hifistyles.colors.text : hifistyles.colors.disabledText
|
color: enabled ? hifistyles.colors.text : hifistyles.colors.disabledText
|
||||||
size: 48
|
size: 48
|
||||||
MouseArea { anchors.fill: parent; onClicked: stackRoot.currentItem.goForward() }
|
MouseArea { anchors.fill: parent; onClicked: goForward() }
|
||||||
}
|
}
|
||||||
|
|
||||||
HiFiGlyphs {
|
HiFiGlyphs {
|
||||||
id: reload;
|
id: reload;
|
||||||
enabled: true;
|
enabled: view != null;
|
||||||
text: webview.loading ? hifi.glyphs.close : hifi.glyphs.reload
|
text: (view !== null && view.loading) ? hifi.glyphs.close : hifi.glyphs.reload
|
||||||
color: enabled ? hifistyles.colors.text : hifistyles.colors.disabledText
|
color: enabled ? hifistyles.colors.text : hifistyles.colors.disabledText
|
||||||
size: 48
|
size: 48
|
||||||
MouseArea { anchors.fill: parent; onClicked: stackRoot.currentItem.reloadPage(); }
|
MouseArea { anchors.fill: parent; onClicked: reloadPage(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -86,7 +89,7 @@ Item {
|
||||||
}
|
}
|
||||||
//root.hidePermissionsBar();
|
//root.hidePermissionsBar();
|
||||||
web.keyboardRaised = false;
|
web.keyboardRaised = false;
|
||||||
stackRoot.currentItem.gotoPage(text);
|
gotoPage(text);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
@ -94,35 +97,43 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ListModel {
|
||||||
|
id: pagesModel
|
||||||
StackView {
|
onCountChanged: {
|
||||||
id: stackRoot
|
currentPage = count - 1
|
||||||
width: parent.width
|
}
|
||||||
height: parent.height - web.headerHeight
|
}
|
||||||
anchors.top: buttons.bottom
|
|
||||||
//property var goBack: currentItem.goBack();
|
|
||||||
property WebEngineView view: root
|
|
||||||
|
|
||||||
initialItem: root;
|
|
||||||
|
|
||||||
function goBack() {
|
function goBack() {
|
||||||
if (depth > 1 ) {
|
if (currentPage > 0) {
|
||||||
if (currentItem.canGoBack) {
|
currentPage--;
|
||||||
currentItem.goBack();
|
|
||||||
} else {
|
|
||||||
stackRoot.pop();
|
|
||||||
currentItem.webView.focus = true;
|
|
||||||
currentItem.webView.forceActiveFocus();
|
|
||||||
web.address = currentItem.webView.url;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (currentItem.canGoBack) {
|
|
||||||
currentItem.goBack();
|
|
||||||
} else if (parentStackItem) {
|
|
||||||
web.parentStackItem.pop();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function goForward() {
|
||||||
|
if (currentPage < pagesModel.count - 1) {
|
||||||
|
currentPage++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function gotoPage(url) {
|
||||||
|
pagesModel.append({webUrl: url})
|
||||||
|
}
|
||||||
|
|
||||||
|
function reloadPage() {
|
||||||
|
view.reloadAndBypassCache()
|
||||||
|
view.setActiveFocusOnPress(true);
|
||||||
|
view.setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
onCurrentPageChanged: {
|
||||||
|
if (currentPage >= 0 && currentPage < pagesModel.count && loader.item !== null) {
|
||||||
|
loader.item.url = pagesModel.get(currentPage).webUrl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onUrlChanged: {
|
||||||
|
gotoPage(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
|
@ -131,120 +142,33 @@ Item {
|
||||||
property var eventBridge;
|
property var eventBridge;
|
||||||
}
|
}
|
||||||
|
|
||||||
WebEngineView {
|
Loader {
|
||||||
id: root
|
id: loader
|
||||||
objectName: "webEngineView"
|
|
||||||
x: 0
|
property WebEngineView currentView: null
|
||||||
y: 0
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: keyboardEnabled && keyboardRaised ? (parent.height - keyboard.height) : parent.height
|
height: parent.height - web.headerHeight
|
||||||
profile: HFTabletWebEngineProfile {
|
asynchronous: true
|
||||||
id: webviewTabletProfile
|
anchors.top: buttons.bottom
|
||||||
storageName: "qmlTabletWebEngine"
|
active: false
|
||||||
}
|
source: "../TabletBrowser.qml"
|
||||||
|
onStatusChanged: {
|
||||||
property WebEngineView webView: root
|
if (loader.status === Loader.Ready) {
|
||||||
function reloadPage() {
|
currentView = item.webView
|
||||||
root.reload();
|
item.webView.userScriptUrl = web.scriptURL
|
||||||
}
|
if (currentPage >= 0) {
|
||||||
|
//we got something to load already
|
||||||
function gotoPage(url) {
|
item.url = pagesModel.get(currentPage).webUrl
|
||||||
root.url = url;
|
|
||||||
}
|
|
||||||
|
|
||||||
property string userScriptUrl: ""
|
|
||||||
|
|
||||||
// creates a global EventBridge object.
|
|
||||||
WebEngineScript {
|
|
||||||
id: createGlobalEventBridge
|
|
||||||
sourceCode: eventBridgeJavaScriptToInject
|
|
||||||
injectionPoint: WebEngineScript.DocumentCreation
|
|
||||||
worldId: WebEngineScript.MainWorld
|
|
||||||
}
|
|
||||||
|
|
||||||
// detects when to raise and lower virtual keyboard
|
|
||||||
WebEngineScript {
|
|
||||||
id: raiseAndLowerKeyboard
|
|
||||||
injectionPoint: WebEngineScript.Deferred
|
|
||||||
sourceUrl: resourceDirectoryUrl + "/html/raiseAndLowerKeyboard.js"
|
|
||||||
worldId: WebEngineScript.MainWorld
|
|
||||||
}
|
|
||||||
|
|
||||||
// User script.
|
|
||||||
WebEngineScript {
|
|
||||||
id: userScript
|
|
||||||
sourceUrl: root.userScriptUrl
|
|
||||||
injectionPoint: WebEngineScript.DocumentReady // DOM ready but page load may not be finished.
|
|
||||||
worldId: WebEngineScript.MainWorld
|
|
||||||
}
|
|
||||||
|
|
||||||
userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ]
|
|
||||||
|
|
||||||
property string newUrl: ""
|
|
||||||
|
|
||||||
webChannel.registeredObjects: [eventBridgeWrapper]
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
// Ensure the JS from the web-engine makes it to our logging
|
|
||||||
root.javaScriptConsoleMessage.connect(function(level, message, lineNumber, sourceID) {
|
|
||||||
console.log("Web Entity JS message: " + sourceID + " " + lineNumber + " " + message);
|
|
||||||
});
|
|
||||||
|
|
||||||
root.profile.httpUserAgent = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36"
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
onFeaturePermissionRequested: {
|
|
||||||
grantFeaturePermission(securityOrigin, feature, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
onLoadingChanged: {
|
|
||||||
keyboardRaised = false;
|
|
||||||
punctuationMode = false;
|
|
||||||
keyboard.resetShiftMode(false);
|
|
||||||
// Required to support clicking on "hifi://" links
|
|
||||||
if (WebEngineView.LoadStartedStatus == loadRequest.status) {
|
|
||||||
var url = loadRequest.url.toString();
|
|
||||||
if (urlHandler.canHandleUrl(url)) {
|
|
||||||
if (urlHandler.handleUrl(url)) {
|
|
||||||
root.stop();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onNewViewRequested:{
|
|
||||||
var component = Qt.createComponent("../TabletBrowser.qml");
|
|
||||||
if (component.status != Component.Ready) {
|
|
||||||
if (component.status == Component.Error) {
|
|
||||||
console.log("Error: " + component.errorString());
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var newWindow = component.createObject();
|
|
||||||
newWindow.setProfile(root.profile);
|
|
||||||
request.openIn(newWindow.webView);
|
|
||||||
newWindow.eventBridge = web.eventBridge;
|
|
||||||
stackRoot.push(newWindow);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HiFiControls.Keyboard {
|
|
||||||
id: keyboard
|
|
||||||
raised: web.keyboardEnabled && web.keyboardRaised
|
|
||||||
numeric: web.punctuationMode
|
|
||||||
anchors {
|
|
||||||
left: parent.left
|
|
||||||
right: parent.right
|
|
||||||
bottom: parent.bottom
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
web.isDesktop = (typeof desktop !== "undefined");
|
web.isDesktop = (typeof desktop !== "undefined");
|
||||||
address = url;
|
address = url;
|
||||||
|
loader.active = true
|
||||||
}
|
}
|
||||||
|
|
||||||
Keys.onPressed: {
|
Keys.onPressed: {
|
||||||
|
|
|
@ -127,7 +127,7 @@ Rectangle {
|
||||||
text: hifi.glyphs.mic
|
text: hifi.glyphs.mic
|
||||||
color: hifi.colors.primaryHighlight
|
color: hifi.colors.primaryHighlight
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
font.pointSize: 27
|
size: 32
|
||||||
}
|
}
|
||||||
RalewayRegular {
|
RalewayRegular {
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
@ -182,7 +182,7 @@ Rectangle {
|
||||||
text: hifi.glyphs.unmuted
|
text: hifi.glyphs.unmuted
|
||||||
color: hifi.colors.primaryHighlight
|
color: hifi.colors.primaryHighlight
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
font.pointSize: 27
|
size: 32
|
||||||
}
|
}
|
||||||
RalewayRegular {
|
RalewayRegular {
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
|
@ -14,6 +14,7 @@ import QtQuick.Controls 1.4
|
||||||
import QtQuick.Controls.Styles 1.4
|
import QtQuick.Controls.Styles 1.4
|
||||||
import QtGraphicalEffects 1.0
|
import QtGraphicalEffects 1.0
|
||||||
import "../styles-uit"
|
import "../styles-uit"
|
||||||
|
import "../controls-uit" as HifiControls
|
||||||
import "toolbars"
|
import "toolbars"
|
||||||
|
|
||||||
// references Users, UserActivityLogger, MyAvatar, Vec3, Quat, AddressManager from root context
|
// references Users, UserActivityLogger, MyAvatar, Vec3, Quat, AddressManager from root context
|
||||||
|
@ -42,8 +43,9 @@ Item {
|
||||||
property bool selected: false
|
property bool selected: false
|
||||||
property bool isAdmin: false
|
property bool isAdmin: false
|
||||||
property bool isPresent: true
|
property bool isPresent: true
|
||||||
|
property string placeName: ""
|
||||||
property string profilePicBorderColor: (connectionStatus == "connection" ? hifi.colors.indigoAccent : (connectionStatus == "friend" ? hifi.colors.greenHighlight : "transparent"))
|
property string profilePicBorderColor: (connectionStatus == "connection" ? hifi.colors.indigoAccent : (connectionStatus == "friend" ? hifi.colors.greenHighlight : "transparent"))
|
||||||
|
property alias avImage: avatarImage
|
||||||
Item {
|
Item {
|
||||||
id: avatarImage
|
id: avatarImage
|
||||||
visible: profileUrl !== "" && userName !== "";
|
visible: profileUrl !== "" && userName !== "";
|
||||||
|
@ -79,25 +81,6 @@ Item {
|
||||||
anchors.fill: parent;
|
anchors.fill: parent;
|
||||||
visible: userImage.status != Image.Ready;
|
visible: userImage.status != Image.Ready;
|
||||||
}
|
}
|
||||||
StateImage {
|
|
||||||
id: infoHoverImage;
|
|
||||||
visible: false;
|
|
||||||
imageURL: "../../images/info-icon-2-state.svg";
|
|
||||||
size: 32;
|
|
||||||
buttonState: 1;
|
|
||||||
anchors.centerIn: parent;
|
|
||||||
}
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
enabled: selected || isMyCard;
|
|
||||||
hoverEnabled: enabled
|
|
||||||
onClicked: {
|
|
||||||
userInfoViewer.url = defaultBaseUrl + "/users/" + userName;
|
|
||||||
userInfoViewer.visible = true;
|
|
||||||
}
|
|
||||||
onEntered: infoHoverImage.visible = true;
|
|
||||||
onExited: infoHoverImage.visible = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Colored border around avatarImage
|
// Colored border around avatarImage
|
||||||
|
@ -316,9 +299,10 @@ Item {
|
||||||
visible: thisNameCard.userName !== "";
|
visible: thisNameCard.userName !== "";
|
||||||
// Size
|
// Size
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: pal.activeTab == "nearbyTab" || isMyCard ? usernameTextPixelSize + 4 : parent.height;
|
height: usernameTextPixelSize + 4
|
||||||
// Anchors
|
// Anchors
|
||||||
anchors.top: isMyCard ? myDisplayName.bottom : (pal.activeTab == "nearbyTab" ? displayNameContainer.bottom : parent.top);
|
anchors.top: isMyCard ? myDisplayName.bottom : pal.activeTab == "nearbyTab" ? displayNameContainer.bottom : undefined //(parent.height - displayNameTextPixelSize/2));
|
||||||
|
anchors.verticalCenter: pal.activeTab == "connectionsTab" ? avatarImage.verticalCenter : undefined
|
||||||
anchors.left: avatarImage.right;
|
anchors.left: avatarImage.right;
|
||||||
anchors.leftMargin: avatarImage.visible ? 5 : 0;
|
anchors.leftMargin: avatarImage.visible ? 5 : 0;
|
||||||
anchors.rightMargin: 5;
|
anchors.rightMargin: 5;
|
||||||
|
@ -346,6 +330,92 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
StateImage {
|
||||||
|
id: nameCardConnectionInfoImage
|
||||||
|
visible: selected && !isMyCard && pal.activeTab == "connectionsTab"
|
||||||
|
imageURL: "../../images/info-icon-2-state.svg" // PLACEHOLDER!!!
|
||||||
|
size: 32;
|
||||||
|
buttonState: 0;
|
||||||
|
anchors.left: avatarImage.right
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
}
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill:nameCardConnectionInfoImage
|
||||||
|
enabled: selected
|
||||||
|
hoverEnabled: true
|
||||||
|
onClicked: {
|
||||||
|
userInfoViewer.url = defaultBaseUrl + "/users/" + userName;
|
||||||
|
userInfoViewer.visible = true;
|
||||||
|
}
|
||||||
|
onEntered: {
|
||||||
|
nameCardConnectionInfoImage.buttonState = 1;
|
||||||
|
}
|
||||||
|
onExited: {
|
||||||
|
nameCardConnectionInfoImage.buttonState = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FiraSansRegular {
|
||||||
|
id: nameCardConnectionInfoText
|
||||||
|
visible: selected && !isMyCard && pal.activeTab == "connectionsTab" && !isMyCard
|
||||||
|
width: parent.width
|
||||||
|
height: displayNameTextPixelSize
|
||||||
|
size: displayNameTextPixelSize - 4
|
||||||
|
anchors.left: nameCardConnectionInfoImage.right
|
||||||
|
anchors.verticalCenter: nameCardConnectionInfoImage.verticalCenter
|
||||||
|
anchors.leftMargin: 5
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
text: "Info"
|
||||||
|
color: hifi.colors.baseGray
|
||||||
|
}
|
||||||
|
HiFiGlyphs {
|
||||||
|
id: nameCardRemoveConnectionImage
|
||||||
|
visible: selected && !isMyCard && pal.activeTab == "connectionsTab"
|
||||||
|
text: hifi.glyphs.close
|
||||||
|
size: 28;
|
||||||
|
x: 120
|
||||||
|
anchors.verticalCenter: nameCardConnectionInfoImage.verticalCenter
|
||||||
|
}
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill:nameCardRemoveConnectionImage
|
||||||
|
enabled: selected
|
||||||
|
hoverEnabled: true
|
||||||
|
onClicked: {
|
||||||
|
// send message to pal.js to forgetConnection
|
||||||
|
pal.sendToScript({method: 'removeConnection', params: thisNameCard.userName});
|
||||||
|
}
|
||||||
|
onEntered: {
|
||||||
|
nameCardRemoveConnectionImage.text = hifi.glyphs.closeInverted;
|
||||||
|
}
|
||||||
|
onExited: {
|
||||||
|
nameCardRemoveConnectionImage.text = hifi.glyphs.close;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FiraSansRegular {
|
||||||
|
id: nameCardRemoveConnectionText
|
||||||
|
visible: selected && !isMyCard && pal.activeTab == "connectionsTab" && !isMyCard
|
||||||
|
width: parent.width
|
||||||
|
height: displayNameTextPixelSize
|
||||||
|
size: displayNameTextPixelSize - 4
|
||||||
|
anchors.left: nameCardRemoveConnectionImage.right
|
||||||
|
anchors.verticalCenter: nameCardRemoveConnectionImage.verticalCenter
|
||||||
|
anchors.leftMargin: 5
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
text: "Forget"
|
||||||
|
color: hifi.colors.baseGray
|
||||||
|
}
|
||||||
|
HifiControls.Button {
|
||||||
|
id: visitConnectionButton
|
||||||
|
visible: selected && !isMyCard && pal.activeTab == "connectionsTab" && !isMyCard
|
||||||
|
text: "Visit"
|
||||||
|
enabled: thisNameCard.placeName !== ""
|
||||||
|
anchors.verticalCenter: nameCardRemoveConnectionImage.verticalCenter
|
||||||
|
x: 240
|
||||||
|
onClicked: {
|
||||||
|
AddressManager.goToUser(thisNameCard.userName);
|
||||||
|
UserActivityLogger.palAction("go_to_user", thisNameCard.userName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// VU Meter
|
// VU Meter
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: nameCardVUMeter
|
id: nameCardVUMeter
|
||||||
|
|
|
@ -52,6 +52,13 @@ Rectangle {
|
||||||
id: letterboxMessage;
|
id: letterboxMessage;
|
||||||
z: 999; // Force the popup on top of everything else
|
z: 999; // Force the popup on top of everything else
|
||||||
}
|
}
|
||||||
|
Connections {
|
||||||
|
target: GlobalServices
|
||||||
|
onMyUsernameChanged: {
|
||||||
|
myData.userName = Account.username;
|
||||||
|
myDataChanged(); // Setting a property within an object isn't enough to update dependencies. This will do it.
|
||||||
|
}
|
||||||
|
}
|
||||||
// The ComboDialog used for setting availability
|
// The ComboDialog used for setting availability
|
||||||
ComboDialog {
|
ComboDialog {
|
||||||
id: comboDialog;
|
id: comboDialog;
|
||||||
|
@ -436,7 +443,7 @@ Rectangle {
|
||||||
rowDelegate: Rectangle { // The only way I know to specify a row height.
|
rowDelegate: Rectangle { // The only way I know to specify a row height.
|
||||||
// Size
|
// Size
|
||||||
height: rowHeight + (styleData.selected ? 15 : 0);
|
height: rowHeight + (styleData.selected ? 15 : 0);
|
||||||
color: rowColor(styleData.selected, styleData.alternate);
|
color: nearbyRowColor(styleData.selected, styleData.alternate);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This Item refers to the contents of each Cell
|
// This Item refers to the contents of each Cell
|
||||||
|
@ -749,7 +756,7 @@ Rectangle {
|
||||||
resizable: false;
|
resizable: false;
|
||||||
}
|
}
|
||||||
TableViewColumn {
|
TableViewColumn {
|
||||||
role: "friends";
|
role: "connection";
|
||||||
title: "FRIEND";
|
title: "FRIEND";
|
||||||
width: actionButtonWidth;
|
width: actionButtonWidth;
|
||||||
movable: false;
|
movable: false;
|
||||||
|
@ -763,8 +770,8 @@ Rectangle {
|
||||||
// This Rectangle refers to each Row in the connectionsTable.
|
// This Rectangle refers to each Row in the connectionsTable.
|
||||||
rowDelegate: Rectangle {
|
rowDelegate: Rectangle {
|
||||||
// Size
|
// Size
|
||||||
height: rowHeight;
|
height: rowHeight + (styleData.selected ? 15 : 0);
|
||||||
color: rowColor(styleData.selected, styleData.alternate);
|
color: connectionsRowColor(styleData.selected, styleData.alternate);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This Item refers to the contents of each Cell
|
// This Item refers to the contents of each Cell
|
||||||
|
@ -779,6 +786,7 @@ Rectangle {
|
||||||
profileUrl: (model && model.profileUrl) || "";
|
profileUrl: (model && model.profileUrl) || "";
|
||||||
displayName: "";
|
displayName: "";
|
||||||
userName: model ? model.userName : "";
|
userName: model ? model.userName : "";
|
||||||
|
placeName: model ? model.placeName : ""
|
||||||
connectionStatus : model ? model.connection : "";
|
connectionStatus : model ? model.connection : "";
|
||||||
selected: styleData.selected;
|
selected: styleData.selected;
|
||||||
// Size
|
// Size
|
||||||
|
@ -797,12 +805,16 @@ Rectangle {
|
||||||
elide: Text.ElideRight;
|
elide: Text.ElideRight;
|
||||||
// Size
|
// Size
|
||||||
width: parent.width;
|
width: parent.width;
|
||||||
// Anchors
|
// you would think that this would work:
|
||||||
anchors.fill: parent;
|
// anchors.verticalCenter: connectionsNameCard.avImage.verticalCenter
|
||||||
|
// but no! you cannot anchor to a non-sibling or parent. So I will
|
||||||
|
// align with the friends checkbox, where I did the manual alignment
|
||||||
|
anchors.verticalCenter: friendsCheckBox.verticalCenter
|
||||||
// Text Size
|
// Text Size
|
||||||
size: 16;
|
size: 16;
|
||||||
// Text Positioning
|
// Text Positioning
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
// Style
|
// Style
|
||||||
color: hifi.colors.blueAccent;
|
color: hifi.colors.blueAccent;
|
||||||
font.underline: true;
|
font.underline: true;
|
||||||
|
@ -822,12 +834,16 @@ Rectangle {
|
||||||
// "Friends" checkbox
|
// "Friends" checkbox
|
||||||
HifiControlsUit.CheckBox {
|
HifiControlsUit.CheckBox {
|
||||||
id: friendsCheckBox;
|
id: friendsCheckBox;
|
||||||
visible: styleData.role === "friends" && model.userName !== myData.userName;
|
visible: styleData.role === "connection" && model && model.userName !== myData.userName;
|
||||||
anchors.centerIn: parent;
|
// you would think that this would work:
|
||||||
checked: model ? (model["connection"] === "friend" ? true : false) : false;
|
// anchors.verticalCenter: connectionsNameCard.avImage.verticalCenter
|
||||||
|
// but no! you cannot anchor to a non-sibling or parent. So:
|
||||||
|
x: parent.width/2 - boxSize/2;
|
||||||
|
y: connectionsNameCard.avImage.y + connectionsNameCard.avImage.height/2 - boxSize/2;
|
||||||
|
checked: model && (model.connection === "friend");
|
||||||
boxSize: 24;
|
boxSize: 24;
|
||||||
onClicked: {
|
onClicked: {
|
||||||
var newValue = !(model["connection"] === "friend");
|
var newValue = model.connection !== "friend";
|
||||||
connectionsUserModel.setProperty(model.userIndex, styleData.role, newValue);
|
connectionsUserModel.setProperty(model.userIndex, styleData.role, newValue);
|
||||||
connectionsUserModelData[model.userIndex][styleData.role] = newValue; // Defensive programming
|
connectionsUserModelData[model.userIndex][styleData.role] = newValue; // Defensive programming
|
||||||
pal.sendToScript({method: newValue ? 'addFriend' : 'removeFriend', params: model.userName});
|
pal.sendToScript({method: newValue ? 'addFriend' : 'removeFriend', params: model.userName});
|
||||||
|
@ -901,7 +917,7 @@ Rectangle {
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
textFormat: Text.StyledText;
|
textFormat: Text.StyledText;
|
||||||
// Text
|
// Text
|
||||||
text: HMD.active ?
|
text: HMD.isMounted ?
|
||||||
"<b>When you meet someone you want to remember later, you can <font color='purple'>connect</font> with a handshake:</b><br><br>" +
|
"<b>When you meet someone you want to remember later, you can <font color='purple'>connect</font> with a handshake:</b><br><br>" +
|
||||||
"1. Put your hand out onto their hand and squeeze your controller's grip button on its side.<br>" +
|
"1. Put your hand out onto their hand and squeeze your controller's grip button on its side.<br>" +
|
||||||
"2. Once the other person puts their hand onto yours, you'll see your connection form.<br>" +
|
"2. Once the other person puts their hand onto yours, you'll see your connection form.<br>" +
|
||||||
|
@ -960,7 +976,6 @@ Rectangle {
|
||||||
// Text size
|
// Text size
|
||||||
size: hifi.fontSizes.tabularData;
|
size: hifi.fontSizes.tabularData;
|
||||||
// Anchors
|
// Anchors
|
||||||
anchors.top: myCard.top;
|
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
// Style
|
// Style
|
||||||
color: hifi.colors.baseGrayHighlight;
|
color: hifi.colors.baseGrayHighlight;
|
||||||
|
@ -1184,9 +1199,12 @@ Rectangle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function rowColor(selected, alternate) {
|
function nearbyRowColor(selected, alternate) {
|
||||||
return selected ? hifi.colors.orangeHighlight : alternate ? hifi.colors.tableRowLightEven : hifi.colors.tableRowLightOdd;
|
return selected ? hifi.colors.orangeHighlight : alternate ? hifi.colors.tableRowLightEven : hifi.colors.tableRowLightOdd;
|
||||||
}
|
}
|
||||||
|
function connectionsRowColor(selected, alternate) {
|
||||||
|
return selected ? hifi.colors.lightBlueHighlight : alternate ? hifi.colors.tableRowLightEven : hifi.colors.tableRowLightOdd;
|
||||||
|
}
|
||||||
function findNearbySessionIndex(sessionId, optionalData) { // no findIndex in .qml
|
function findNearbySessionIndex(sessionId, optionalData) { // no findIndex in .qml
|
||||||
var data = optionalData || nearbyUserModelData, length = data.length;
|
var data = optionalData || nearbyUserModelData, length = data.length;
|
||||||
for (var i = 0; i < length; i++) {
|
for (var i = 0; i < length; i++) {
|
||||||
|
@ -1257,6 +1275,8 @@ Rectangle {
|
||||||
selectionTimer.userIndex = userIndex;
|
selectionTimer.userIndex = userIndex;
|
||||||
selectionTimer.start();
|
selectionTimer.start();
|
||||||
}
|
}
|
||||||
|
// in any case make sure we are in the nearby tab
|
||||||
|
activeTab="nearbyTab";
|
||||||
break;
|
break;
|
||||||
// Received an "updateUsername()" request from the JS
|
// Received an "updateUsername()" request from the JS
|
||||||
case 'updateUsername':
|
case 'updateUsername':
|
||||||
|
|
|
@ -21,6 +21,9 @@ Rectangle {
|
||||||
id: root
|
id: root
|
||||||
objectName: "AssetServer"
|
objectName: "AssetServer"
|
||||||
|
|
||||||
|
property string title: "Asset Browser"
|
||||||
|
property bool keyboardRaised: false
|
||||||
|
|
||||||
property var eventBridge;
|
property var eventBridge;
|
||||||
signal sendToScript(var message);
|
signal sendToScript(var message);
|
||||||
property bool isHMD: false
|
property bool isHMD: false
|
||||||
|
@ -415,7 +418,6 @@ Rectangle {
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
y: hifi.dimensions.tabletMenuHeader //-bgNavBar
|
|
||||||
spacing: 10
|
spacing: 10
|
||||||
|
|
||||||
HifiControls.TabletContentSection {
|
HifiControls.TabletContentSection {
|
||||||
|
|
|
@ -20,7 +20,7 @@ import "../../windows"
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: root
|
id: root
|
||||||
objectName: "RunningScripts"
|
objectName: "RunningScripts"
|
||||||
property var title: "Running Scripts"
|
property string title: "Running Scripts"
|
||||||
HifiConstants { id: hifi }
|
HifiConstants { id: hifi }
|
||||||
signal sendToScript(var message);
|
signal sendToScript(var message);
|
||||||
property var eventBridge;
|
property var eventBridge;
|
||||||
|
@ -81,9 +81,9 @@ Rectangle {
|
||||||
|
|
||||||
Flickable {
|
Flickable {
|
||||||
id: flickable
|
id: flickable
|
||||||
width: parent.width
|
width: tabletRoot.width
|
||||||
height: parent.height - (keyboard.raised ? keyboard.raisedHeight : 0)
|
height: parent.height - (keyboard.raised ? keyboard.raisedHeight : 0)
|
||||||
contentWidth: parent.width
|
contentWidth: column.width
|
||||||
contentHeight: column.childrenRect.height
|
contentHeight: column.childrenRect.height
|
||||||
clip: true
|
clip: true
|
||||||
|
|
||||||
|
@ -121,9 +121,8 @@ Rectangle {
|
||||||
model: runningScriptsModel
|
model: runningScriptsModel
|
||||||
id: table
|
id: table
|
||||||
height: 185
|
height: 185
|
||||||
|
width: parent.width
|
||||||
colorScheme: hifi.colorSchemes.dark
|
colorScheme: hifi.colorSchemes.dark
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
expandSelectedRow: true
|
expandSelectedRow: true
|
||||||
|
|
||||||
itemDelegate: Item {
|
itemDelegate: Item {
|
||||||
|
|
|
@ -22,15 +22,20 @@ Rectangle {
|
||||||
color: hifi.colors.baseGray;
|
color: hifi.colors.baseGray;
|
||||||
property var eventBridge;
|
property var eventBridge;
|
||||||
signal sendToScript(var message);
|
signal sendToScript(var message);
|
||||||
|
property bool keyboardEnabled: false
|
||||||
|
property bool punctuationMode: false
|
||||||
|
property bool keyboardRasied: false
|
||||||
|
|
||||||
Column {
|
Item {
|
||||||
id: column1
|
id: column1
|
||||||
anchors.rightMargin: 10
|
anchors.rightMargin: 10
|
||||||
anchors.leftMargin: 10
|
anchors.leftMargin: 10
|
||||||
anchors.bottomMargin: 10
|
anchors.bottomMargin: 10
|
||||||
anchors.topMargin: 10
|
anchors.topMargin: 10
|
||||||
anchors.fill: parent
|
anchors.top: parent.top
|
||||||
spacing: 5
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.bottom: keyboard.top
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
id: text1
|
id: text1
|
||||||
|
@ -43,17 +48,42 @@ Rectangle {
|
||||||
id: modelURL
|
id: modelURL
|
||||||
height: 20
|
height: 20
|
||||||
text: qsTr("")
|
text: qsTr("")
|
||||||
|
color: "white"
|
||||||
|
anchors.top: text1.bottom
|
||||||
|
anchors.topMargin: 5
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.leftMargin: 0
|
anchors.leftMargin: 0
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: 0
|
anchors.rightMargin: 0
|
||||||
font.pixelSize: 12
|
font.pixelSize: 12
|
||||||
|
|
||||||
|
onAccepted: {
|
||||||
|
newModelDialog.keyboardEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: {
|
||||||
|
newModelDialog.keyboardEnabled = HMD.active
|
||||||
|
parent.focus = true;
|
||||||
|
parent.forceActiveFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: textInputBox
|
||||||
|
color: "white"
|
||||||
|
anchors.fill: modelURL
|
||||||
|
opacity: 0.1
|
||||||
}
|
}
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
id: row1
|
id: row1
|
||||||
height: 400
|
height: 400
|
||||||
spacing: 30
|
spacing: 30
|
||||||
|
anchors.top: modelURL.top
|
||||||
|
anchors.topMargin: 25
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.leftMargin: 0
|
anchors.leftMargin: 0
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
@ -155,4 +185,15 @@ Rectangle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Keyboard {
|
||||||
|
id: keyboard
|
||||||
|
raised: parent.keyboardEnabled
|
||||||
|
numeric: parent.punctuationMode
|
||||||
|
anchors {
|
||||||
|
bottom: parent.bottom
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,7 +202,7 @@ Item {
|
||||||
|
|
||||||
RalewaySemiBold {
|
RalewaySemiBold {
|
||||||
id: usernameText
|
id: usernameText
|
||||||
text: tablet.parent.parent.username
|
text: tabletRoot.username
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: 20
|
anchors.rightMargin: 20
|
||||||
|
|
|
@ -25,8 +25,8 @@ StackView {
|
||||||
HifiConstants { id: hifi }
|
HifiConstants { id: hifi }
|
||||||
HifiStyles.HifiConstants { id: hifiStyleConstants }
|
HifiStyles.HifiConstants { id: hifiStyleConstants }
|
||||||
initialItem: addressBarDialog
|
initialItem: addressBarDialog
|
||||||
width: parent.width
|
width: parent !== null ? parent.width : undefined
|
||||||
height: parent.height
|
height: parent !== null ? parent.height : undefined
|
||||||
property var eventBridge;
|
property var eventBridge;
|
||||||
property var allStories: [];
|
property var allStories: [];
|
||||||
property int cardWidth: 460;
|
property int cardWidth: 460;
|
||||||
|
@ -107,7 +107,7 @@ StackView {
|
||||||
imageURL: "../../../images/home.svg"
|
imageURL: "../../../images/home.svg"
|
||||||
onClicked: {
|
onClicked: {
|
||||||
addressBarDialog.loadHome();
|
addressBarDialog.loadHome();
|
||||||
root.shown = false;
|
tabletRoot.shown = false;
|
||||||
}
|
}
|
||||||
anchors {
|
anchors {
|
||||||
left: parent.left
|
left: parent.left
|
||||||
|
@ -142,7 +142,9 @@ StackView {
|
||||||
anchors {
|
anchors {
|
||||||
top: navBar.bottom
|
top: navBar.bottom
|
||||||
right: parent.right
|
right: parent.right
|
||||||
|
rightMargin: 16
|
||||||
left: parent.left
|
left: parent.left
|
||||||
|
leftMargin: 16
|
||||||
}
|
}
|
||||||
|
|
||||||
property int inputAreaHeight: 70
|
property int inputAreaHeight: 70
|
||||||
|
@ -291,8 +293,6 @@ StackView {
|
||||||
left: parent.left
|
left: parent.left
|
||||||
right: parent.right
|
right: parent.right
|
||||||
leftMargin: 10
|
leftMargin: 10
|
||||||
verticalCenter: parent.verticalCenter;
|
|
||||||
horizontalCenter: parent.horizontalCenter;
|
|
||||||
}
|
}
|
||||||
model: suggestions
|
model: suggestions
|
||||||
orientation: ListView.Vertical
|
orientation: ListView.Vertical
|
||||||
|
@ -547,14 +547,14 @@ StackView {
|
||||||
if (addressLine.text !== "") {
|
if (addressLine.text !== "") {
|
||||||
addressBarDialog.loadAddress(addressLine.text, fromSuggestions)
|
addressBarDialog.loadAddress(addressLine.text, fromSuggestions)
|
||||||
}
|
}
|
||||||
root.shown = false;
|
tabletRoot.shown = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Keys.onPressed: {
|
Keys.onPressed: {
|
||||||
switch (event.key) {
|
switch (event.key) {
|
||||||
case Qt.Key_Escape:
|
case Qt.Key_Escape:
|
||||||
case Qt.Key_Back:
|
case Qt.Key_Back:
|
||||||
root.shown = false
|
tabletRoot.shown = false
|
||||||
clearAddressLineTimer.start();
|
clearAddressLineTimer.start();
|
||||||
event.accepted = true
|
event.accepted = true
|
||||||
break
|
break
|
||||||
|
|
|
@ -13,6 +13,7 @@ Item {
|
||||||
property var openMessage: null;
|
property var openMessage: null;
|
||||||
property string subMenu: ""
|
property string subMenu: ""
|
||||||
signal showDesktop();
|
signal showDesktop();
|
||||||
|
property bool shown: true
|
||||||
|
|
||||||
function setOption(value) {
|
function setOption(value) {
|
||||||
option = value;
|
option = value;
|
||||||
|
|
|
@ -72,6 +72,7 @@ Item {
|
||||||
readonly property color magentaAccent: "#A2277C"
|
readonly property color magentaAccent: "#A2277C"
|
||||||
readonly property color checkboxCheckedRed: "#FF0000"
|
readonly property color checkboxCheckedRed: "#FF0000"
|
||||||
readonly property color checkboxCheckedBorderRed: "#D00000"
|
readonly property color checkboxCheckedBorderRed: "#D00000"
|
||||||
|
readonly property color lightBlueHighlight: "#d6f6ff"
|
||||||
|
|
||||||
// Semitransparent
|
// Semitransparent
|
||||||
readonly property color darkGray30: "#4d121212"
|
readonly property color darkGray30: "#4d121212"
|
||||||
|
|
|
@ -76,8 +76,8 @@ void JSConsole::setScriptEngine(ScriptEngine* scriptEngine) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_scriptEngine != NULL) {
|
if (_scriptEngine != NULL) {
|
||||||
disconnect(_scriptEngine, SIGNAL(printedMessage(const QString&)), this, SLOT(handlePrint(const QString&)));
|
disconnect(_scriptEngine, &ScriptEngine::printedMessage, this, &JSConsole::handlePrint);
|
||||||
disconnect(_scriptEngine, SIGNAL(errorMessage(const QString&)), this, SLOT(handleError(const QString&)));
|
disconnect(_scriptEngine, &ScriptEngine::errorMessage, this, &JSConsole::handleError);
|
||||||
if (_ownScriptEngine) {
|
if (_ownScriptEngine) {
|
||||||
_scriptEngine->deleteLater();
|
_scriptEngine->deleteLater();
|
||||||
}
|
}
|
||||||
|
@ -87,8 +87,8 @@ void JSConsole::setScriptEngine(ScriptEngine* scriptEngine) {
|
||||||
_ownScriptEngine = scriptEngine == NULL;
|
_ownScriptEngine = scriptEngine == NULL;
|
||||||
_scriptEngine = _ownScriptEngine ? DependencyManager::get<ScriptEngines>()->loadScript(QString(), false) : scriptEngine;
|
_scriptEngine = _ownScriptEngine ? DependencyManager::get<ScriptEngines>()->loadScript(QString(), false) : scriptEngine;
|
||||||
|
|
||||||
connect(_scriptEngine, SIGNAL(printedMessage(const QString&)), this, SLOT(handlePrint(const QString&)));
|
connect(_scriptEngine, &ScriptEngine::printedMessage, this, &JSConsole::handlePrint);
|
||||||
connect(_scriptEngine, SIGNAL(errorMessage(const QString&)), this, SLOT(handleError(const QString&)));
|
connect(_scriptEngine, &ScriptEngine::errorMessage, this, &JSConsole::handleError);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JSConsole::executeCommand(const QString& command) {
|
void JSConsole::executeCommand(const QString& command) {
|
||||||
|
@ -134,11 +134,13 @@ void JSConsole::commandFinished() {
|
||||||
resetCurrentCommandHistory();
|
resetCurrentCommandHistory();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JSConsole::handleError(const QString& message) {
|
void JSConsole::handleError(const QString& scriptName, const QString& message) {
|
||||||
|
Q_UNUSED(scriptName);
|
||||||
appendMessage(GUTTER_ERROR, "<span style='" + RESULT_ERROR_STYLE + "'>" + message.toHtmlEscaped() + "</span>");
|
appendMessage(GUTTER_ERROR, "<span style='" + RESULT_ERROR_STYLE + "'>" + message.toHtmlEscaped() + "</span>");
|
||||||
}
|
}
|
||||||
|
|
||||||
void JSConsole::handlePrint(const QString& message) {
|
void JSConsole::handlePrint(const QString& scriptName, const QString& message) {
|
||||||
|
Q_UNUSED(scriptName);
|
||||||
appendMessage("", message);
|
appendMessage("", message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,8 +47,8 @@ protected:
|
||||||
protected slots:
|
protected slots:
|
||||||
void scrollToBottom();
|
void scrollToBottom();
|
||||||
void resizeTextInput();
|
void resizeTextInput();
|
||||||
void handlePrint(const QString& message);
|
void handlePrint(const QString& scriptName, const QString& message);
|
||||||
void handleError(const QString& message);
|
void handleError(const QString& scriptName, const QString& message);
|
||||||
void commandFinished();
|
void commandFinished();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -158,6 +158,22 @@ namespace controller {
|
||||||
LEFT_HAND_PINKY2,
|
LEFT_HAND_PINKY2,
|
||||||
LEFT_HAND_PINKY3,
|
LEFT_HAND_PINKY3,
|
||||||
LEFT_HAND_PINKY4,
|
LEFT_HAND_PINKY4,
|
||||||
|
TRACKED_OBJECT_00,
|
||||||
|
TRACKED_OBJECT_01,
|
||||||
|
TRACKED_OBJECT_02,
|
||||||
|
TRACKED_OBJECT_03,
|
||||||
|
TRACKED_OBJECT_04,
|
||||||
|
TRACKED_OBJECT_05,
|
||||||
|
TRACKED_OBJECT_06,
|
||||||
|
TRACKED_OBJECT_07,
|
||||||
|
TRACKED_OBJECT_08,
|
||||||
|
TRACKED_OBJECT_09,
|
||||||
|
TRACKED_OBJECT_10,
|
||||||
|
TRACKED_OBJECT_11,
|
||||||
|
TRACKED_OBJECT_12,
|
||||||
|
TRACKED_OBJECT_13,
|
||||||
|
TRACKED_OBJECT_14,
|
||||||
|
TRACKED_OBJECT_15,
|
||||||
NUM_STANDARD_POSES
|
NUM_STANDARD_POSES
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -182,6 +182,7 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI
|
||||||
if (!wantsLocked) {
|
if (!wantsLocked) {
|
||||||
EntityItemProperties tempProperties;
|
EntityItemProperties tempProperties;
|
||||||
tempProperties.setLocked(wantsLocked);
|
tempProperties.setLocked(wantsLocked);
|
||||||
|
tempProperties.setLastEdited(properties.getLastEdited());
|
||||||
|
|
||||||
bool success;
|
bool success;
|
||||||
AACube queryCube = entity->getQueryAACube(success);
|
AACube queryCube = entity->getQueryAACube(success);
|
||||||
|
|
|
@ -60,6 +60,7 @@ bool OffscreenGLCanvas::create(QOpenGLContext* sharedContext) {
|
||||||
bool OffscreenGLCanvas::makeCurrent() {
|
bool OffscreenGLCanvas::makeCurrent() {
|
||||||
bool result = _context->makeCurrent(_offscreenSurface);
|
bool result = _context->makeCurrent(_offscreenSurface);
|
||||||
Q_ASSERT(result);
|
Q_ASSERT(result);
|
||||||
|
|
||||||
std::call_once(_reportOnce, [this]{
|
std::call_once(_reportOnce, [this]{
|
||||||
qCDebug(glLogging) << "GL Version: " << QString((const char*) glGetString(GL_VERSION));
|
qCDebug(glLogging) << "GL Version: " << QString((const char*) glGetString(GL_VERSION));
|
||||||
qCDebug(glLogging) << "GL Shader Language Version: " << QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION));
|
qCDebug(glLogging) << "GL Shader Language Version: " << QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION));
|
||||||
|
|
|
@ -278,11 +278,9 @@ void OffscreenQmlSurface::cleanup() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OffscreenQmlSurface::render() {
|
void OffscreenQmlSurface::render() {
|
||||||
|
|
||||||
#ifdef HIFI_ENABLE_NSIGHT_DEBUG
|
#ifdef HIFI_ENABLE_NSIGHT_DEBUG
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (_paused) {
|
if (_paused) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -614,7 +612,11 @@ QObject* OffscreenQmlSurface::finishQmlLoad(std::function<void(QQmlContext*, QOb
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//check if the item contains sendToScript signal
|
||||||
|
int sendToScriptIndex = newItem->metaObject()->indexOfSignal("sendToScript");
|
||||||
|
if (sendToScriptIndex != -1) {
|
||||||
connect(newItem, SIGNAL(sendToScript(QVariant)), this, SIGNAL(fromQml(QVariant)));
|
connect(newItem, SIGNAL(sendToScript(QVariant)), this, SIGNAL(fromQml(QVariant)));
|
||||||
|
}
|
||||||
|
|
||||||
// The root item is ready. Associate it with the window.
|
// The root item is ready. Associate it with the window.
|
||||||
_rootItem = newItem;
|
_rootItem = newItem;
|
||||||
|
|
|
@ -61,6 +61,16 @@ void UserActivityLoggerScriptingInterface::palOpened(float secondsOpened) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UserActivityLoggerScriptingInterface::makeUserConnection(QString otherID, bool success, QString detailsString) {
|
||||||
|
QJsonObject payload;
|
||||||
|
payload["otherUser"] = otherID;
|
||||||
|
payload["success"] = success;
|
||||||
|
if (detailsString.length() > 0) {
|
||||||
|
payload["details"] = detailsString;
|
||||||
|
}
|
||||||
|
logAction("makeUserConnection", payload);
|
||||||
|
}
|
||||||
|
|
||||||
void UserActivityLoggerScriptingInterface::logAction(QString action, QJsonObject details) {
|
void UserActivityLoggerScriptingInterface::logAction(QString action, QJsonObject details) {
|
||||||
QMetaObject::invokeMethod(&UserActivityLogger::getInstance(), "logAction",
|
QMetaObject::invokeMethod(&UserActivityLogger::getInstance(), "logAction",
|
||||||
Q_ARG(QString, action),
|
Q_ARG(QString, action),
|
||||||
|
|
|
@ -29,6 +29,7 @@ public:
|
||||||
float tutorialElapsedTime, QString tutorialRunID = "", int tutorialVersion = 0, QString controllerType = "");
|
float tutorialElapsedTime, QString tutorialRunID = "", int tutorialVersion = 0, QString controllerType = "");
|
||||||
Q_INVOKABLE void palAction(QString action, QString target);
|
Q_INVOKABLE void palAction(QString action, QString target);
|
||||||
Q_INVOKABLE void palOpened(float secondsOpen);
|
Q_INVOKABLE void palOpened(float secondsOpen);
|
||||||
|
Q_INVOKABLE void makeUserConnection(QString otherUser, bool success, QString details="");
|
||||||
private:
|
private:
|
||||||
void logAction(QString action, QJsonObject details = {});
|
void logAction(QString action, QJsonObject details = {});
|
||||||
};
|
};
|
||||||
|
|
|
@ -28,6 +28,12 @@
|
||||||
#include "skin_model_shadow_vert.h"
|
#include "skin_model_shadow_vert.h"
|
||||||
#include "skin_model_normal_map_vert.h"
|
#include "skin_model_normal_map_vert.h"
|
||||||
|
|
||||||
|
#include "simple_vert.h"
|
||||||
|
#include "simple_textured_frag.h"
|
||||||
|
#include "simple_textured_unlit_frag.h"
|
||||||
|
#include "simple_transparent_textured_frag.h"
|
||||||
|
#include "simple_transparent_textured_unlit_frag.h"
|
||||||
|
|
||||||
#include "model_frag.h"
|
#include "model_frag.h"
|
||||||
#include "model_unlit_frag.h"
|
#include "model_unlit_frag.h"
|
||||||
#include "model_shadow_frag.h"
|
#include "model_shadow_frag.h"
|
||||||
|
@ -135,6 +141,7 @@ void initOverlay3DPipelines(ShapePlumber& plumber) {
|
||||||
|
|
||||||
void initDeferredPipelines(render::ShapePlumber& plumber) {
|
void initDeferredPipelines(render::ShapePlumber& plumber) {
|
||||||
// Vertex shaders
|
// Vertex shaders
|
||||||
|
auto simpleVertex = gpu::Shader::createVertex(std::string(simple_vert));
|
||||||
auto modelVertex = gpu::Shader::createVertex(std::string(model_vert));
|
auto modelVertex = gpu::Shader::createVertex(std::string(model_vert));
|
||||||
auto modelNormalMapVertex = gpu::Shader::createVertex(std::string(model_normal_map_vert));
|
auto modelNormalMapVertex = gpu::Shader::createVertex(std::string(model_normal_map_vert));
|
||||||
auto modelLightmapVertex = gpu::Shader::createVertex(std::string(model_lightmap_vert));
|
auto modelLightmapVertex = gpu::Shader::createVertex(std::string(model_lightmap_vert));
|
||||||
|
@ -145,6 +152,10 @@ void initDeferredPipelines(render::ShapePlumber& plumber) {
|
||||||
auto skinModelShadowVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_vert));
|
auto skinModelShadowVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_vert));
|
||||||
|
|
||||||
// Pixel shaders
|
// Pixel shaders
|
||||||
|
auto simplePixel = gpu::Shader::createPixel(std::string(simple_textured_frag));
|
||||||
|
auto simpleUnlitPixel = gpu::Shader::createPixel(std::string(simple_textured_unlit_frag));
|
||||||
|
auto simpleTranslucentPixel = gpu::Shader::createPixel(std::string(simple_transparent_textured_frag));
|
||||||
|
auto simpleTranslucentUnlitPixel = gpu::Shader::createPixel(std::string(simple_transparent_textured_unlit_frag));
|
||||||
auto modelPixel = gpu::Shader::createPixel(std::string(model_frag));
|
auto modelPixel = gpu::Shader::createPixel(std::string(model_frag));
|
||||||
auto modelUnlitPixel = gpu::Shader::createPixel(std::string(model_unlit_frag));
|
auto modelUnlitPixel = gpu::Shader::createPixel(std::string(model_unlit_frag));
|
||||||
auto modelNormalMapPixel = gpu::Shader::createPixel(std::string(model_normal_map_frag));
|
auto modelNormalMapPixel = gpu::Shader::createPixel(std::string(model_normal_map_frag));
|
||||||
|
@ -167,13 +178,13 @@ void initDeferredPipelines(render::ShapePlumber& plumber) {
|
||||||
modelVertex, modelPixel);
|
modelVertex, modelPixel);
|
||||||
addPipeline(
|
addPipeline(
|
||||||
Key::Builder(),
|
Key::Builder(),
|
||||||
modelVertex, modelPixel);
|
simpleVertex, simplePixel);
|
||||||
addPipeline(
|
addPipeline(
|
||||||
Key::Builder().withMaterial().withUnlit(),
|
Key::Builder().withMaterial().withUnlit(),
|
||||||
modelVertex, modelUnlitPixel);
|
modelVertex, modelUnlitPixel);
|
||||||
addPipeline(
|
addPipeline(
|
||||||
Key::Builder().withUnlit(),
|
Key::Builder().withUnlit(),
|
||||||
modelVertex, modelUnlitPixel);
|
simpleVertex, simpleUnlitPixel);
|
||||||
addPipeline(
|
addPipeline(
|
||||||
Key::Builder().withMaterial().withTangents(),
|
Key::Builder().withMaterial().withTangents(),
|
||||||
modelNormalMapVertex, modelNormalMapPixel);
|
modelNormalMapVertex, modelNormalMapPixel);
|
||||||
|
@ -189,13 +200,13 @@ void initDeferredPipelines(render::ShapePlumber& plumber) {
|
||||||
modelVertex, modelTranslucentPixel);
|
modelVertex, modelTranslucentPixel);
|
||||||
addPipeline(
|
addPipeline(
|
||||||
Key::Builder().withTranslucent(),
|
Key::Builder().withTranslucent(),
|
||||||
modelVertex, modelTranslucentPixel);
|
simpleVertex, simpleTranslucentPixel);
|
||||||
addPipeline(
|
addPipeline(
|
||||||
Key::Builder().withMaterial().withTranslucent().withUnlit(),
|
Key::Builder().withMaterial().withTranslucent().withUnlit(),
|
||||||
modelVertex, modelTranslucentUnlitPixel);
|
modelVertex, modelTranslucentUnlitPixel);
|
||||||
addPipeline(
|
addPipeline(
|
||||||
Key::Builder().withTranslucent().withUnlit(),
|
Key::Builder().withTranslucent().withUnlit(),
|
||||||
modelVertex, modelTranslucentUnlitPixel);
|
simpleVertex, simpleTranslucentUnlitPixel);
|
||||||
addPipeline(
|
addPipeline(
|
||||||
Key::Builder().withMaterial().withTranslucent().withTangents(),
|
Key::Builder().withMaterial().withTranslucent().withTangents(),
|
||||||
modelNormalMapVertex, modelTranslucentPixel);
|
modelNormalMapVertex, modelTranslucentPixel);
|
||||||
|
|
|
@ -26,15 +26,17 @@ in vec2 _texCoord0;
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
vec4 texel = texture(originalTexture, _texCoord0);
|
vec4 texel = texture(originalTexture, _texCoord0);
|
||||||
|
float colorAlpha = _color.a;
|
||||||
if (_color.a <= 0.0) {
|
if (_color.a <= 0.0) {
|
||||||
texel = colorToLinearRGBA(texel);
|
texel = colorToLinearRGBA(texel);
|
||||||
|
colorAlpha = -_color.a;
|
||||||
}
|
}
|
||||||
|
|
||||||
const float ALPHA_THRESHOLD = 0.999;
|
const float ALPHA_THRESHOLD = 0.999;
|
||||||
if (_color.a * texel.a < ALPHA_THRESHOLD) {
|
if (colorAlpha * texel.a < ALPHA_THRESHOLD) {
|
||||||
packDeferredFragmentTranslucent(
|
packDeferredFragmentTranslucent(
|
||||||
normalize(_normal),
|
normalize(_normal),
|
||||||
_color.a * texel.a,
|
colorAlpha * texel.a,
|
||||||
_color.rgb * texel.rgb,
|
_color.rgb * texel.rgb,
|
||||||
DEFAULT_FRESNEL,
|
DEFAULT_FRESNEL,
|
||||||
DEFAULT_ROUGHNESS);
|
DEFAULT_ROUGHNESS);
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<$VERSION_HEADER$>
|
<$VERSION_HEADER$>
|
||||||
// Generated on <$_SCRIBE_DATE$>
|
// Generated on <$_SCRIBE_DATE$>
|
||||||
//
|
//
|
||||||
// simple.frag
|
// simple_textured_unlit.frag
|
||||||
// fragment shader
|
// fragment shader
|
||||||
//
|
//
|
||||||
// Created by Clément Brisset on 5/29/15.
|
// Created by Clément Brisset on 5/29/15.
|
||||||
|
@ -25,15 +25,17 @@ in vec2 _texCoord0;
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
vec4 texel = texture(originalTexture, _texCoord0.st);
|
vec4 texel = texture(originalTexture, _texCoord0.st);
|
||||||
|
float colorAlpha = _color.a;
|
||||||
if (_color.a <= 0.0) {
|
if (_color.a <= 0.0) {
|
||||||
texel = colorToLinearRGBA(texel);
|
texel = colorToLinearRGBA(texel);
|
||||||
|
colorAlpha = -_color.a;
|
||||||
}
|
}
|
||||||
|
|
||||||
const float ALPHA_THRESHOLD = 0.999;
|
const float ALPHA_THRESHOLD = 0.999;
|
||||||
if (_color.a * texel.a < ALPHA_THRESHOLD) {
|
if (colorAlpha * texel.a < ALPHA_THRESHOLD) {
|
||||||
packDeferredFragmentTranslucent(
|
packDeferredFragmentTranslucent(
|
||||||
normalize(_normal),
|
normalize(_normal),
|
||||||
_color.a * texel.a,
|
colorAlpha * texel.a,
|
||||||
_color.rgb * texel.rgb,
|
_color.rgb * texel.rgb,
|
||||||
DEFAULT_FRESNEL,
|
DEFAULT_FRESNEL,
|
||||||
DEFAULT_ROUGHNESS);
|
DEFAULT_ROUGHNESS);
|
||||||
|
|
62
libraries/render-utils/src/simple_transparent_textured.slf
Normal file
62
libraries/render-utils/src/simple_transparent_textured.slf
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
<@include gpu/Config.slh@>
|
||||||
|
<$VERSION_HEADER$>
|
||||||
|
// Generated on <$_SCRIBE_DATE$>
|
||||||
|
//
|
||||||
|
// simple_transparent_textured.slf
|
||||||
|
// fragment shader
|
||||||
|
//
|
||||||
|
// Created by Sam Gateau on 4/3/17.
|
||||||
|
// Copyright 2017 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
<@include gpu/Color.slh@>
|
||||||
|
|
||||||
|
<@include DeferredBufferWrite.slh@>
|
||||||
|
<@include DeferredGlobalLight.slh@>
|
||||||
|
<$declareEvalGlobalLightingAlphaBlended()$>
|
||||||
|
|
||||||
|
<@include gpu/Transform.slh@>
|
||||||
|
<$declareStandardCameraTransform()$>
|
||||||
|
|
||||||
|
// the albedo texture
|
||||||
|
uniform sampler2D originalTexture;
|
||||||
|
|
||||||
|
// the interpolated normal
|
||||||
|
in vec4 _position;
|
||||||
|
in vec3 _normal;
|
||||||
|
in vec4 _color;
|
||||||
|
in vec2 _texCoord0;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
vec4 texel = texture(originalTexture, _texCoord0.st);
|
||||||
|
float opacity = _color.a;
|
||||||
|
if (_color.a <= 0.0) {
|
||||||
|
texel = colorToLinearRGBA(texel);
|
||||||
|
opacity = -_color.a;
|
||||||
|
}
|
||||||
|
opacity *= texel.a;
|
||||||
|
vec3 albedo = _color.rgb * texel.rgb;
|
||||||
|
|
||||||
|
vec3 fragPosition = _position.xyz;
|
||||||
|
vec3 fragNormal = normalize(_normal);
|
||||||
|
|
||||||
|
TransformCamera cam = getTransformCamera();
|
||||||
|
|
||||||
|
_fragColor0 = vec4(evalGlobalLightingAlphaBlended(
|
||||||
|
cam._viewInverse,
|
||||||
|
1.0,
|
||||||
|
1.0,
|
||||||
|
fragPosition,
|
||||||
|
fragNormal,
|
||||||
|
albedo,
|
||||||
|
DEFAULT_FRESNEL,
|
||||||
|
0.0,
|
||||||
|
vec3(0.0f),
|
||||||
|
DEFAULT_ROUGHNESS,
|
||||||
|
opacity),
|
||||||
|
opacity);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
<@include gpu/Config.slh@>
|
||||||
|
<$VERSION_HEADER$>
|
||||||
|
// Generated on <$_SCRIBE_DATE$>
|
||||||
|
//
|
||||||
|
// simple_transparent_textured_unlit.slf
|
||||||
|
// fragment shader
|
||||||
|
//
|
||||||
|
// Created by Sam Gateau on 4/3/17.
|
||||||
|
// Copyright 2017 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
<@include gpu/Color.slh@>
|
||||||
|
|
||||||
|
// the albedo texture
|
||||||
|
uniform sampler2D originalTexture;
|
||||||
|
|
||||||
|
// the interpolated normal
|
||||||
|
in vec3 _normal;
|
||||||
|
in vec4 _color;
|
||||||
|
in vec2 _texCoord0;
|
||||||
|
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 _fragColor0;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
vec4 texel = texture(originalTexture, _texCoord0.st);
|
||||||
|
float colorAlpha = _color.a;
|
||||||
|
if (_color.a <= 0.0) {
|
||||||
|
texel = colorToLinearRGBA(texel);
|
||||||
|
colorAlpha = -_color.a;
|
||||||
|
}
|
||||||
|
_fragColor0 = vec4(_color.rgb * texel.rgb, colorAlpha * texel.a);
|
||||||
|
}
|
|
@ -122,11 +122,14 @@ void QmlWindowClass::initQml(QVariantMap properties) {
|
||||||
object->setProperty(OFFSCREEN_VISIBILITY_PROPERTY, visible);
|
object->setProperty(OFFSCREEN_VISIBILITY_PROPERTY, visible);
|
||||||
object->setProperty(SOURCE_PROPERTY, _source);
|
object->setProperty(SOURCE_PROPERTY, _source);
|
||||||
|
|
||||||
|
const QMetaObject *metaObject = _qmlWindow->metaObject();
|
||||||
// Forward messages received from QML on to the script
|
// Forward messages received from QML on to the script
|
||||||
connect(_qmlWindow, SIGNAL(sendToScript(QVariant)), this, SLOT(qmlToScript(const QVariant&)), Qt::QueuedConnection);
|
connect(_qmlWindow, SIGNAL(sendToScript(QVariant)), this, SLOT(qmlToScript(const QVariant&)), Qt::QueuedConnection);
|
||||||
connect(_qmlWindow, SIGNAL(visibleChanged()), this, SIGNAL(visibleChanged()), Qt::QueuedConnection);
|
connect(_qmlWindow, SIGNAL(visibleChanged()), this, SIGNAL(visibleChanged()), Qt::QueuedConnection);
|
||||||
|
|
||||||
|
if (metaObject->indexOfSignal("resized") >= 0)
|
||||||
connect(_qmlWindow, SIGNAL(resized(QSizeF)), this, SIGNAL(resized(QSizeF)), Qt::QueuedConnection);
|
connect(_qmlWindow, SIGNAL(resized(QSizeF)), this, SIGNAL(resized(QSizeF)), Qt::QueuedConnection);
|
||||||
|
if (metaObject->indexOfSignal("moved") >= 0)
|
||||||
connect(_qmlWindow, SIGNAL(moved(QVector2D)), this, SLOT(hasMoved(QVector2D)), Qt::QueuedConnection);
|
connect(_qmlWindow, SIGNAL(moved(QVector2D)), this, SLOT(hasMoved(QVector2D)), Qt::QueuedConnection);
|
||||||
connect(_qmlWindow, SIGNAL(windowClosed()), this, SLOT(hasClosed()), Qt::QueuedConnection);
|
connect(_qmlWindow, SIGNAL(windowClosed()), this, SLOT(hasClosed()), Qt::QueuedConnection);
|
||||||
});
|
});
|
||||||
|
|
|
@ -33,6 +33,8 @@ static const char* MENU_PATH = "Avatar" ">" "Oculus Touch Controllers";
|
||||||
|
|
||||||
const char* OculusControllerManager::NAME = "Oculus";
|
const char* OculusControllerManager::NAME = "Oculus";
|
||||||
|
|
||||||
|
const quint64 LOST_TRACKING_DELAY = 3000000;
|
||||||
|
|
||||||
bool OculusControllerManager::isSupported() const {
|
bool OculusControllerManager::isSupported() const {
|
||||||
return oculusAvailable();
|
return oculusAvailable();
|
||||||
}
|
}
|
||||||
|
@ -207,9 +209,7 @@ void OculusControllerManager::RemoteDevice::focusOutEvent() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OculusControllerManager::TouchDevice::update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) {
|
void OculusControllerManager::TouchDevice::update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) {
|
||||||
_poseStateMap.clear();
|
|
||||||
_buttonPressedMap.clear();
|
_buttonPressedMap.clear();
|
||||||
|
|
||||||
ovrSessionStatus status;
|
ovrSessionStatus status;
|
||||||
if (!OVR_SUCCESS(ovr_GetSessionStatus(_parent._session, &status)) || (ovrFalse == status.HmdMounted)) {
|
if (!OVR_SUCCESS(ovr_GetSessionStatus(_parent._session, &status)) || (ovrFalse == status.HmdMounted)) {
|
||||||
// if the HMD isn't on someone's head, don't take input from the controllers
|
// if the HMD isn't on someone's head, don't take input from the controllers
|
||||||
|
@ -217,15 +217,33 @@ void OculusControllerManager::TouchDevice::update(float deltaTime, const control
|
||||||
}
|
}
|
||||||
|
|
||||||
int numTrackedControllers = 0;
|
int numTrackedControllers = 0;
|
||||||
|
quint64 currentTime = usecTimestampNow();
|
||||||
static const auto REQUIRED_HAND_STATUS = ovrStatus_OrientationTracked | ovrStatus_PositionTracked;
|
static const auto REQUIRED_HAND_STATUS = ovrStatus_OrientationTracked | ovrStatus_PositionTracked;
|
||||||
auto tracking = ovr_GetTrackingState(_parent._session, 0, false);
|
auto tracking = ovr_GetTrackingState(_parent._session, 0, false);
|
||||||
ovr_for_each_hand([&](ovrHandType hand) {
|
ovr_for_each_hand([&](ovrHandType hand) {
|
||||||
++numTrackedControllers;
|
++numTrackedControllers;
|
||||||
|
int controller = (hand == ovrHand_Left ? controller::LEFT_HAND : controller::RIGHT_HAND);
|
||||||
if (REQUIRED_HAND_STATUS == (tracking.HandStatusFlags[hand] & REQUIRED_HAND_STATUS)) {
|
if (REQUIRED_HAND_STATUS == (tracking.HandStatusFlags[hand] & REQUIRED_HAND_STATUS)) {
|
||||||
|
_poseStateMap.erase(controller);
|
||||||
handlePose(deltaTime, inputCalibrationData, hand, tracking.HandPoses[hand]);
|
handlePose(deltaTime, inputCalibrationData, hand, tracking.HandPoses[hand]);
|
||||||
} else {
|
_lostTracking[controller] = false;
|
||||||
_poseStateMap[hand == ovrHand_Left ? controller::LEFT_HAND : controller::RIGHT_HAND].valid = false;
|
_lastControllerPose[controller] = tracking.HandPoses[hand];
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_lostTracking[controller]) {
|
||||||
|
if (currentTime > _regainTrackingDeadline[controller]) {
|
||||||
|
_poseStateMap.erase(controller);
|
||||||
|
_poseStateMap[controller].valid = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
quint64 deadlineToRegainTracking = currentTime + LOST_TRACKING_DELAY;
|
||||||
|
_regainTrackingDeadline[controller] = deadlineToRegainTracking;
|
||||||
|
_lostTracking[controller] = true;
|
||||||
|
}
|
||||||
|
handleRotationForUntrackedHand(inputCalibrationData, hand, tracking.HandPoses[hand]);
|
||||||
});
|
});
|
||||||
using namespace controller;
|
using namespace controller;
|
||||||
// Axes
|
// Axes
|
||||||
|
@ -286,6 +304,16 @@ void OculusControllerManager::TouchDevice::handlePose(float deltaTime,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OculusControllerManager::TouchDevice::handleRotationForUntrackedHand(const controller::InputCalibrationData& inputCalibrationData,
|
||||||
|
ovrHandType hand, const ovrPoseStatef& handPose) {
|
||||||
|
auto poseId = (hand == ovrHand_Left ? controller::LEFT_HAND : controller::RIGHT_HAND);
|
||||||
|
auto& pose = _poseStateMap[poseId];
|
||||||
|
auto lastHandPose = _lastControllerPose[poseId];
|
||||||
|
pose = ovrControllerRotationToHandRotation(hand, handPose, lastHandPose);
|
||||||
|
glm::mat4 controllerToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat;
|
||||||
|
pose = pose.transform(controllerToAvatar);
|
||||||
|
}
|
||||||
|
|
||||||
bool OculusControllerManager::TouchDevice::triggerHapticPulse(float strength, float duration, controller::Hand hand) {
|
bool OculusControllerManager::TouchDevice::triggerHapticPulse(float strength, float duration, controller::Hand hand) {
|
||||||
Locker locker(_lock);
|
Locker locker(_lock);
|
||||||
bool toReturn = true;
|
bool toReturn = true;
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include <GLMHelpers.h>
|
#include <GLMHelpers.h>
|
||||||
|
|
||||||
|
@ -75,6 +76,7 @@ private:
|
||||||
private:
|
private:
|
||||||
void stopHapticPulse(bool leftHand);
|
void stopHapticPulse(bool leftHand);
|
||||||
void handlePose(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, ovrHandType hand, const ovrPoseStatef& handPose);
|
void handlePose(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, ovrHandType hand, const ovrPoseStatef& handPose);
|
||||||
|
void handleRotationForUntrackedHand(const controller::InputCalibrationData& inputCalibrationData, ovrHandType hand, const ovrPoseStatef& handPose);
|
||||||
int _trackedControllers { 0 };
|
int _trackedControllers { 0 };
|
||||||
|
|
||||||
// perform an action when the TouchDevice mutex is acquired.
|
// perform an action when the TouchDevice mutex is acquired.
|
||||||
|
@ -87,6 +89,9 @@ private:
|
||||||
float _rightHapticDuration { 0.0f };
|
float _rightHapticDuration { 0.0f };
|
||||||
float _rightHapticStrength { 0.0f };
|
float _rightHapticStrength { 0.0f };
|
||||||
mutable std::recursive_mutex _lock;
|
mutable std::recursive_mutex _lock;
|
||||||
|
std::map<int, bool> _lostTracking;
|
||||||
|
std::map<int, quint64> _regainTrackingDeadline;
|
||||||
|
std::map<int, ovrPoseStatef> _lastControllerPose;
|
||||||
|
|
||||||
friend class OculusControllerManager;
|
friend class OculusControllerManager;
|
||||||
};
|
};
|
||||||
|
|
|
@ -267,3 +267,37 @@ controller::Pose ovrControllerPoseToHandPose(
|
||||||
pose.valid = true;
|
pose.valid = true;
|
||||||
return pose;
|
return pose;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
controller::Pose ovrControllerRotationToHandRotation(ovrHandType hand, const ovrPoseStatef& handPose,
|
||||||
|
const ovrPoseStatef& lastHandPose) {
|
||||||
|
static const glm::quat yFlip = glm::angleAxis(PI, Vectors::UNIT_Y);
|
||||||
|
static const glm::quat quarterX = glm::angleAxis(PI_OVER_TWO, Vectors::UNIT_X);
|
||||||
|
static const glm::quat touchToHand = yFlip * quarterX;
|
||||||
|
|
||||||
|
static const glm::quat leftQuarterZ = glm::angleAxis(-PI_OVER_TWO, Vectors::UNIT_Z);
|
||||||
|
static const glm::quat rightQuarterZ = glm::angleAxis(PI_OVER_TWO, Vectors::UNIT_Z);
|
||||||
|
|
||||||
|
static const glm::quat leftRotationOffset = glm::inverse(leftQuarterZ) * touchToHand;
|
||||||
|
static const glm::quat rightRotationOffset = glm::inverse(rightQuarterZ) * touchToHand;
|
||||||
|
|
||||||
|
static const float CONTROLLER_LENGTH_OFFSET = 0.0762f; // three inches
|
||||||
|
static const glm::vec3 CONTROLLER_OFFSET = glm::vec3(CONTROLLER_LENGTH_OFFSET / 2.0f,
|
||||||
|
-CONTROLLER_LENGTH_OFFSET / 2.0f,
|
||||||
|
CONTROLLER_LENGTH_OFFSET * 1.5f);
|
||||||
|
static const glm::vec3 leftTranslationOffset = glm::vec3(-1.0f, 1.0f, 1.0f) * CONTROLLER_OFFSET;
|
||||||
|
static const glm::vec3 rightTranslationOffset = CONTROLLER_OFFSET;
|
||||||
|
|
||||||
|
auto translationOffset = (hand == ovrHand_Left ? leftTranslationOffset : rightTranslationOffset);
|
||||||
|
auto rotationOffset = (hand == ovrHand_Left ? leftRotationOffset : rightRotationOffset);
|
||||||
|
|
||||||
|
glm::quat rotation = toGlm(handPose.ThePose.Orientation);
|
||||||
|
|
||||||
|
controller::Pose pose;
|
||||||
|
pose.translation = toGlm(lastHandPose.ThePose.Position);
|
||||||
|
pose.translation += rotation * translationOffset;
|
||||||
|
pose.rotation = rotation * rotationOffset;
|
||||||
|
pose.angularVelocity = toGlm(lastHandPose.AngularVelocity);
|
||||||
|
pose.velocity = toGlm(lastHandPose.LinearVelocity);
|
||||||
|
pose.valid = true;
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
|
@ -118,3 +118,6 @@ inline ovrPosef ovrPoseFromGlm(const glm::mat4 & m) {
|
||||||
controller::Pose ovrControllerPoseToHandPose(
|
controller::Pose ovrControllerPoseToHandPose(
|
||||||
ovrHandType hand,
|
ovrHandType hand,
|
||||||
const ovrPoseStatef& handPose);
|
const ovrPoseStatef& handPose);
|
||||||
|
|
||||||
|
controller::Pose ovrControllerRotationToHandRotation(ovrHandType hand,
|
||||||
|
const ovrPoseStatef& handPose, const ovrPoseStatef& lastHandPose);
|
||||||
|
|
|
@ -278,7 +278,7 @@ public:
|
||||||
static const vr::VRTextureBounds_t leftBounds{ 0, 0, 0.5f, 1 };
|
static const vr::VRTextureBounds_t leftBounds{ 0, 0, 0.5f, 1 };
|
||||||
static const vr::VRTextureBounds_t rightBounds{ 0.5f, 0, 1, 1 };
|
static const vr::VRTextureBounds_t rightBounds{ 0.5f, 0, 1, 1 };
|
||||||
|
|
||||||
vr::Texture_t texture{ (void*)_colors[currentColorBuffer], vr::API_OpenGL, vr::ColorSpace_Auto };
|
vr::Texture_t texture{ (void*)_colors[currentColorBuffer], vr::TextureType_OpenGL, vr::ColorSpace_Auto };
|
||||||
vr::VRCompositor()->Submit(vr::Eye_Left, &texture, &leftBounds);
|
vr::VRCompositor()->Submit(vr::Eye_Left, &texture, &leftBounds);
|
||||||
vr::VRCompositor()->Submit(vr::Eye_Right, &texture, &rightBounds);
|
vr::VRCompositor()->Submit(vr::Eye_Right, &texture, &rightBounds);
|
||||||
_plugin._presentRate.increment();
|
_plugin._presentRate.increment();
|
||||||
|
@ -422,7 +422,7 @@ bool OpenVrDisplayPlugin::internalActivate() {
|
||||||
withNonPresentThreadLock([&] {
|
withNonPresentThreadLock([&] {
|
||||||
openvr_for_each_eye([&](vr::Hmd_Eye eye) {
|
openvr_for_each_eye([&](vr::Hmd_Eye eye) {
|
||||||
_eyeOffsets[eye] = toGlm(_system->GetEyeToHeadTransform(eye));
|
_eyeOffsets[eye] = toGlm(_system->GetEyeToHeadTransform(eye));
|
||||||
_eyeProjections[eye] = toGlm(_system->GetProjectionMatrix(eye, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, vr::API_OpenGL));
|
_eyeProjections[eye] = toGlm(_system->GetProjectionMatrix(eye, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP));
|
||||||
});
|
});
|
||||||
// FIXME Calculate the proper combined projection by using GetProjectionRaw values from both eyes
|
// FIXME Calculate the proper combined projection by using GetProjectionRaw values from both eyes
|
||||||
_cullingProjection = _eyeProjections[0];
|
_cullingProjection = _eyeProjections[0];
|
||||||
|
@ -639,7 +639,7 @@ void OpenVrDisplayPlugin::hmdPresent() {
|
||||||
_submitThread->waitForPresent();
|
_submitThread->waitForPresent();
|
||||||
} else {
|
} else {
|
||||||
GLuint glTexId = getGLBackend()->getTextureID(_compositeFramebuffer->getRenderBuffer(0));
|
GLuint glTexId = getGLBackend()->getTextureID(_compositeFramebuffer->getRenderBuffer(0));
|
||||||
vr::Texture_t vrTexture { (void*)glTexId, vr::API_OpenGL, vr::ColorSpace_Auto };
|
vr::Texture_t vrTexture { (void*)glTexId, vr::TextureType_OpenGL, vr::ColorSpace_Auto };
|
||||||
vr::VRCompositor()->Submit(vr::Eye_Left, &vrTexture, &OPENVR_TEXTURE_BOUNDS_LEFT);
|
vr::VRCompositor()->Submit(vr::Eye_Left, &vrTexture, &OPENVR_TEXTURE_BOUNDS_LEFT);
|
||||||
vr::VRCompositor()->Submit(vr::Eye_Right, &vrTexture, &OPENVR_TEXTURE_BOUNDS_RIGHT);
|
vr::VRCompositor()->Submit(vr::Eye_Right, &vrTexture, &OPENVR_TEXTURE_BOUNDS_RIGHT);
|
||||||
vr::VRCompositor()->PostPresentHandoff();
|
vr::VRCompositor()->PostPresentHandoff();
|
||||||
|
|
|
@ -114,7 +114,7 @@ void releaseOpenVrSystem() {
|
||||||
|
|
||||||
// HACK: workaround openvr crash, call submit with an invalid texture, right before VR_Shutdown.
|
// HACK: workaround openvr crash, call submit with an invalid texture, right before VR_Shutdown.
|
||||||
const GLuint INVALID_GL_TEXTURE_HANDLE = -1;
|
const GLuint INVALID_GL_TEXTURE_HANDLE = -1;
|
||||||
vr::Texture_t vrTexture{ (void*)INVALID_GL_TEXTURE_HANDLE, vr::API_OpenGL, vr::ColorSpace_Auto };
|
vr::Texture_t vrTexture{ (void*)INVALID_GL_TEXTURE_HANDLE, vr::TextureType_OpenGL, vr::ColorSpace_Auto };
|
||||||
static vr::VRTextureBounds_t OPENVR_TEXTURE_BOUNDS_LEFT{ 0, 0, 0.5f, 1 };
|
static vr::VRTextureBounds_t OPENVR_TEXTURE_BOUNDS_LEFT{ 0, 0, 0.5f, 1 };
|
||||||
static vr::VRTextureBounds_t OPENVR_TEXTURE_BOUNDS_RIGHT{ 0.5f, 0, 1, 1 };
|
static vr::VRTextureBounds_t OPENVR_TEXTURE_BOUNDS_RIGHT{ 0.5f, 0, 1, 1 };
|
||||||
|
|
||||||
|
|
|
@ -63,59 +63,6 @@ bool ViveControllerManager::activate() {
|
||||||
|
|
||||||
enableOpenVrKeyboard(_container);
|
enableOpenVrKeyboard(_container);
|
||||||
|
|
||||||
// OpenVR provides 3d mesh representations of the controllers
|
|
||||||
// Disabled controller rendering code
|
|
||||||
/*
|
|
||||||
auto renderModels = vr::VRRenderModels();
|
|
||||||
|
|
||||||
vr::RenderModel_t model;
|
|
||||||
if (!_system->LoadRenderModel(CONTROLLER_MODEL_STRING, &model)) {
|
|
||||||
qDebug() << QString("Unable to load render model %1\n").arg(CONTROLLER_MODEL_STRING);
|
|
||||||
} else {
|
|
||||||
model::Mesh* mesh = new model::Mesh();
|
|
||||||
model::MeshPointer meshPtr(mesh);
|
|
||||||
_modelGeometry.setMesh(meshPtr);
|
|
||||||
|
|
||||||
auto indexBuffer = new gpu::Buffer(3 * model.unTriangleCount * sizeof(uint16_t), (gpu::Byte*)model.rIndexData);
|
|
||||||
auto indexBufferPtr = gpu::BufferPointer(indexBuffer);
|
|
||||||
auto indexBufferView = new gpu::BufferView(indexBufferPtr, gpu::Element(gpu::SCALAR, gpu::UINT16, gpu::RAW));
|
|
||||||
mesh->setIndexBuffer(*indexBufferView);
|
|
||||||
|
|
||||||
auto vertexBuffer = new gpu::Buffer(model.unVertexCount * sizeof(vr::RenderModel_Vertex_t),
|
|
||||||
(gpu::Byte*)model.rVertexData);
|
|
||||||
auto vertexBufferPtr = gpu::BufferPointer(vertexBuffer);
|
|
||||||
auto vertexBufferView = new gpu::BufferView(vertexBufferPtr,
|
|
||||||
0,
|
|
||||||
vertexBufferPtr->getSize() - sizeof(float) * 3,
|
|
||||||
sizeof(vr::RenderModel_Vertex_t),
|
|
||||||
gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RAW));
|
|
||||||
mesh->setVertexBuffer(*vertexBufferView);
|
|
||||||
mesh->addAttribute(gpu::Stream::NORMAL,
|
|
||||||
gpu::BufferView(vertexBufferPtr,
|
|
||||||
sizeof(float) * 3,
|
|
||||||
vertexBufferPtr->getSize() - sizeof(float) * 3,
|
|
||||||
sizeof(vr::RenderModel_Vertex_t),
|
|
||||||
gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RAW)));
|
|
||||||
//mesh->addAttribute(gpu::Stream::TEXCOORD,
|
|
||||||
// gpu::BufferView(vertexBufferPtr,
|
|
||||||
// 2 * sizeof(float) * 3,
|
|
||||||
// vertexBufferPtr->getSize() - sizeof(float) * 2,
|
|
||||||
// sizeof(vr::RenderModel_Vertex_t),
|
|
||||||
// gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::RAW)));
|
|
||||||
|
|
||||||
gpu::Element formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA);
|
|
||||||
gpu::Element formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA);
|
|
||||||
_texture = gpu::TexturePointer(
|
|
||||||
gpu::Texture::create2D(formatGPU, model.diffuseTexture.unWidth, model.diffuseTexture.unHeight,
|
|
||||||
gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
|
|
||||||
_texture->assignStoredMip(0, formatMip, model.diffuseTexture.unWidth * model.diffuseTexture.unHeight * 4 * sizeof(uint8_t), model.diffuseTexture.rubTextureMapData);
|
|
||||||
_texture->autoGenerateMips(-1);
|
|
||||||
|
|
||||||
_modelLoaded = true;
|
|
||||||
_renderControllers = true;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// register with UserInputMapper
|
// register with UserInputMapper
|
||||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||||
userInputMapper->registerDevice(_inputDevice);
|
userInputMapper->registerDevice(_inputDevice);
|
||||||
|
@ -145,70 +92,6 @@ void ViveControllerManager::deactivate() {
|
||||||
_registeredWithInputMapper = false;
|
_registeredWithInputMapper = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViveControllerManager::updateRendering(RenderArgs* args, render::ScenePointer scene, render::PendingChanges pendingChanges) {
|
|
||||||
PerformanceTimer perfTimer("ViveControllerManager::updateRendering");
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (_modelLoaded) {
|
|
||||||
//auto controllerPayload = new render::Payload<ViveControllerManager>(this);
|
|
||||||
//auto controllerPayloadPointer = ViveControllerManager::PayloadPointer(controllerPayload);
|
|
||||||
//if (_leftHandRenderID == 0) {
|
|
||||||
// _leftHandRenderID = scene->allocateID();
|
|
||||||
// pendingChanges.resetItem(_leftHandRenderID, controllerPayloadPointer);
|
|
||||||
//}
|
|
||||||
//pendingChanges.updateItem(_leftHandRenderID, );
|
|
||||||
|
|
||||||
|
|
||||||
controller::Pose leftHand = _inputDevice->_poseStateMap[controller::StandardPoseChannel::LEFT_HAND];
|
|
||||||
controller::Pose rightHand = _inputDevice->_poseStateMap[controller::StandardPoseChannel::RIGHT_HAND];
|
|
||||||
|
|
||||||
gpu::doInBatch(args->_context, [=](gpu::Batch& batch) {
|
|
||||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
|
||||||
geometryCache->useSimpleDrawPipeline(batch);
|
|
||||||
DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch, true);
|
|
||||||
|
|
||||||
auto mesh = _modelGeometry.getMesh();
|
|
||||||
batch.setInputFormat(mesh->getVertexFormat());
|
|
||||||
//batch._glBindTexture(GL_TEXTURE_2D, _uexture);
|
|
||||||
|
|
||||||
if (leftHand.isValid()) {
|
|
||||||
renderHand(leftHand, batch, 1);
|
|
||||||
}
|
|
||||||
if (rightHand.isValid()) {
|
|
||||||
renderHand(rightHand, batch, -1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
void ViveControllerManager::renderHand(const controller::Pose& pose, gpu::Batch& batch, int sign) {
|
|
||||||
/*
|
|
||||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
|
||||||
Transform transform(userInputMapper->getSensorToWorldMat());
|
|
||||||
transform.postTranslate(pose.getTranslation() + pose.getRotation() * glm::vec3(0, 0, CONTROLLER_LENGTH_OFFSET));
|
|
||||||
|
|
||||||
glm::quat rotation = pose.getRotation() * glm::angleAxis(PI, glm::vec3(1.0f, 0.0f, 0.0f)) * glm::angleAxis(sign * PI_OVER_TWO, glm::vec3(0.0f, 0.0f, 1.0f));
|
|
||||||
transform.postRotate(rotation);
|
|
||||||
|
|
||||||
batch.setModelTransform(transform);
|
|
||||||
|
|
||||||
auto mesh = _modelGeometry.getMesh();
|
|
||||||
batch.setInputBuffer(gpu::Stream::POSITION, mesh->getVertexBuffer());
|
|
||||||
batch.setInputBuffer(gpu::Stream::NORMAL,
|
|
||||||
mesh->getVertexBuffer()._buffer,
|
|
||||||
sizeof(float) * 3,
|
|
||||||
mesh->getVertexBuffer()._stride);
|
|
||||||
//batch.setInputBuffer(gpu::Stream::TEXCOORD,
|
|
||||||
// mesh->getVertexBuffer()._buffer,
|
|
||||||
// 2 * 3 * sizeof(float),
|
|
||||||
// mesh->getVertexBuffer()._stride);
|
|
||||||
batch.setIndexBuffer(gpu::UINT16, mesh->getIndexBuffer()._buffer, 0);
|
|
||||||
batch.drawIndexed(gpu::TRIANGLES, mesh->getNumIndices(), 0);
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ViveControllerManager::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) {
|
void ViveControllerManager::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) {
|
||||||
|
|
||||||
if (!_system) {
|
if (!_system) {
|
||||||
|
@ -257,6 +140,11 @@ void ViveControllerManager::InputDevice::update(float deltaTime, const controlle
|
||||||
handleHandController(deltaTime, leftHandDeviceIndex, inputCalibrationData, true);
|
handleHandController(deltaTime, leftHandDeviceIndex, inputCalibrationData, true);
|
||||||
handleHandController(deltaTime, rightHandDeviceIndex, inputCalibrationData, false);
|
handleHandController(deltaTime, rightHandDeviceIndex, inputCalibrationData, false);
|
||||||
|
|
||||||
|
// collect poses for all generic trackers
|
||||||
|
for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) {
|
||||||
|
handleTrackedObject(i, inputCalibrationData);
|
||||||
|
}
|
||||||
|
|
||||||
// handle haptics
|
// handle haptics
|
||||||
{
|
{
|
||||||
Locker locker(_lock);
|
Locker locker(_lock);
|
||||||
|
@ -278,6 +166,31 @@ void ViveControllerManager::InputDevice::update(float deltaTime, const controlle
|
||||||
_trackedControllers = numTrackedControllers;
|
_trackedControllers = numTrackedControllers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ViveControllerManager::InputDevice::handleTrackedObject(uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData) {
|
||||||
|
|
||||||
|
uint32_t poseIndex = controller::TRACKED_OBJECT_00 + deviceIndex;
|
||||||
|
|
||||||
|
if (_system->IsTrackedDeviceConnected(deviceIndex) &&
|
||||||
|
_system->GetTrackedDeviceClass(deviceIndex) == vr::TrackedDeviceClass_GenericTracker &&
|
||||||
|
_nextSimPoseData.vrPoses[deviceIndex].bPoseIsValid &&
|
||||||
|
poseIndex <= controller::TRACKED_OBJECT_15) {
|
||||||
|
|
||||||
|
// process pose
|
||||||
|
const mat4& mat = _nextSimPoseData.poses[deviceIndex];
|
||||||
|
const vec3 linearVelocity = _nextSimPoseData.linearVelocities[deviceIndex];
|
||||||
|
const vec3 angularVelocity = _nextSimPoseData.angularVelocities[deviceIndex];
|
||||||
|
|
||||||
|
controller::Pose pose(extractTranslation(mat), glmExtractRotation(mat), linearVelocity, angularVelocity);
|
||||||
|
|
||||||
|
// transform into avatar frame
|
||||||
|
glm::mat4 controllerToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat;
|
||||||
|
_poseStateMap[poseIndex] = pose.transform(controllerToAvatar);
|
||||||
|
} else {
|
||||||
|
controller::Pose invalidPose;
|
||||||
|
_poseStateMap[poseIndex] = invalidPose;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ViveControllerManager::InputDevice::handleHandController(float deltaTime, uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData, bool isLeftHand) {
|
void ViveControllerManager::InputDevice::handleHandController(float deltaTime, uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData, bool isLeftHand) {
|
||||||
|
|
||||||
if (_system->IsTrackedDeviceConnected(deviceIndex) &&
|
if (_system->IsTrackedDeviceConnected(deviceIndex) &&
|
||||||
|
@ -291,7 +204,7 @@ void ViveControllerManager::InputDevice::handleHandController(float deltaTime, u
|
||||||
handlePoseEvent(deltaTime, inputCalibrationData, mat, linearVelocity, angularVelocity, isLeftHand);
|
handlePoseEvent(deltaTime, inputCalibrationData, mat, linearVelocity, angularVelocity, isLeftHand);
|
||||||
|
|
||||||
vr::VRControllerState_t controllerState = vr::VRControllerState_t();
|
vr::VRControllerState_t controllerState = vr::VRControllerState_t();
|
||||||
if (_system->GetControllerState(deviceIndex, &controllerState)) {
|
if (_system->GetControllerState(deviceIndex, &controllerState, sizeof(vr::VRControllerState_t))) {
|
||||||
// process each button
|
// process each button
|
||||||
for (uint32_t i = 0; i < vr::k_EButton_Max; ++i) {
|
for (uint32_t i = 0; i < vr::k_EButton_Max; ++i) {
|
||||||
auto mask = vr::ButtonMaskFromId((vr::EVRButtonId)i);
|
auto mask = vr::ButtonMaskFromId((vr::EVRButtonId)i);
|
||||||
|
@ -492,6 +405,24 @@ controller::Input::NamedVector ViveControllerManager::InputDevice::getAvailableI
|
||||||
makePair(LEFT_HAND, "LeftHand"),
|
makePair(LEFT_HAND, "LeftHand"),
|
||||||
makePair(RIGHT_HAND, "RightHand"),
|
makePair(RIGHT_HAND, "RightHand"),
|
||||||
|
|
||||||
|
// 16 tracked poses
|
||||||
|
makePair(TRACKED_OBJECT_00, "TrackedObject00"),
|
||||||
|
makePair(TRACKED_OBJECT_01, "TrackedObject01"),
|
||||||
|
makePair(TRACKED_OBJECT_02, "TrackedObject02"),
|
||||||
|
makePair(TRACKED_OBJECT_03, "TrackedObject03"),
|
||||||
|
makePair(TRACKED_OBJECT_04, "TrackedObject04"),
|
||||||
|
makePair(TRACKED_OBJECT_05, "TrackedObject05"),
|
||||||
|
makePair(TRACKED_OBJECT_06, "TrackedObject06"),
|
||||||
|
makePair(TRACKED_OBJECT_07, "TrackedObject07"),
|
||||||
|
makePair(TRACKED_OBJECT_08, "TrackedObject08"),
|
||||||
|
makePair(TRACKED_OBJECT_09, "TrackedObject09"),
|
||||||
|
makePair(TRACKED_OBJECT_10, "TrackedObject10"),
|
||||||
|
makePair(TRACKED_OBJECT_11, "TrackedObject11"),
|
||||||
|
makePair(TRACKED_OBJECT_12, "TrackedObject12"),
|
||||||
|
makePair(TRACKED_OBJECT_13, "TrackedObject13"),
|
||||||
|
makePair(TRACKED_OBJECT_14, "TrackedObject14"),
|
||||||
|
makePair(TRACKED_OBJECT_15, "TrackedObject15"),
|
||||||
|
|
||||||
// app button above trackpad.
|
// app button above trackpad.
|
||||||
Input::NamedPair(Input(_deviceID, LEFT_APP_MENU, ChannelType::BUTTON), "LeftApplicationMenu"),
|
Input::NamedPair(Input(_deviceID, LEFT_APP_MENU, ChannelType::BUTTON), "LeftApplicationMenu"),
|
||||||
Input::NamedPair(Input(_deviceID, RIGHT_APP_MENU, ChannelType::BUTTON), "RightApplicationMenu"),
|
Input::NamedPair(Input(_deviceID, RIGHT_APP_MENU, ChannelType::BUTTON), "RightApplicationMenu"),
|
||||||
|
|
|
@ -43,8 +43,6 @@ public:
|
||||||
void pluginFocusOutEvent() override { _inputDevice->focusOutEvent(); }
|
void pluginFocusOutEvent() override { _inputDevice->focusOutEvent(); }
|
||||||
void pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override;
|
void pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override;
|
||||||
|
|
||||||
void updateRendering(RenderArgs* args, render::ScenePointer scene, render::PendingChanges pendingChanges);
|
|
||||||
|
|
||||||
void setRenderControllers(bool renderControllers) { _renderControllers = renderControllers; }
|
void setRenderControllers(bool renderControllers) { _renderControllers = renderControllers; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -62,6 +60,7 @@ private:
|
||||||
void hapticsHelper(float deltaTime, bool leftHand);
|
void hapticsHelper(float deltaTime, bool leftHand);
|
||||||
|
|
||||||
void handleHandController(float deltaTime, uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData, bool isLeftHand);
|
void handleHandController(float deltaTime, uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData, bool isLeftHand);
|
||||||
|
void handleTrackedObject(uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData);
|
||||||
void handleButtonEvent(float deltaTime, uint32_t button, bool pressed, bool touched, bool isLeftHand);
|
void handleButtonEvent(float deltaTime, uint32_t button, bool pressed, bool touched, bool isLeftHand);
|
||||||
void handleAxisEvent(float deltaTime, uint32_t axis, float x, float y, bool isLeftHand);
|
void handleAxisEvent(float deltaTime, uint32_t axis, float x, float y, bool isLeftHand);
|
||||||
void handlePoseEvent(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, const mat4& mat,
|
void handlePoseEvent(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, const mat4& mat,
|
||||||
|
|
|
@ -18,6 +18,9 @@ Rectangle {
|
||||||
width: parent ? parent.width : 100
|
width: parent ? parent.width : 100
|
||||||
height: parent ? parent.height : 100
|
height: parent ? parent.height : 100
|
||||||
|
|
||||||
|
signal moved(vector2d position);
|
||||||
|
signal resized(size size);
|
||||||
|
|
||||||
property var channel;
|
property var channel;
|
||||||
|
|
||||||
TextArea {
|
TextArea {
|
||||||
|
|
36
scripts/developer/tests/viveTrackedObjects.js
Normal file
36
scripts/developer/tests/viveTrackedObjects.js
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
|
||||||
|
var TRACKED_OBJECT_POSES = [
|
||||||
|
"TrackedObject00", "TrackedObject01", "TrackedObject02", "TrackedObject03",
|
||||||
|
"TrackedObject04", "TrackedObject05", "TrackedObject06", "TrackedObject07",
|
||||||
|
"TrackedObject08", "TrackedObject09", "TrackedObject10", "TrackedObject11",
|
||||||
|
"TrackedObject12", "TrackedObject13", "TrackedObject14", "TrackedObject15"
|
||||||
|
];
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
Script.update.connect(update);
|
||||||
|
}
|
||||||
|
|
||||||
|
function shutdown() {
|
||||||
|
Script.update.disconnect(update);
|
||||||
|
|
||||||
|
TRACKED_OBJECT_POSES.forEach(function (key) {
|
||||||
|
DebugDraw.removeMyAvatarMarker(key);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var WHITE = {x: 1, y: 1, z: 1, w: 1};
|
||||||
|
|
||||||
|
function update(dt) {
|
||||||
|
if (Controller.Hardware.Vive) {
|
||||||
|
TRACKED_OBJECT_POSES.forEach(function (key) {
|
||||||
|
var pose = Controller.getPoseValue(Controller.Hardware.Vive[key]);
|
||||||
|
if (pose.valid) {
|
||||||
|
DebugDraw.addMyAvatarMarker(key, pose.rotation, pose.translation, WHITE);
|
||||||
|
} else {
|
||||||
|
DebugDraw.removeMyAvatarMarker(key);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init();
|
|
@ -297,8 +297,9 @@ function Teleporter() {
|
||||||
} else if (teleportLocationType === TARGET.SURFACE) {
|
} else if (teleportLocationType === TARGET.SURFACE) {
|
||||||
var offset = getAvatarFootOffset();
|
var offset = getAvatarFootOffset();
|
||||||
intersection.intersection.y += offset;
|
intersection.intersection.y += offset;
|
||||||
MyAvatar.position = intersection.intersection;
|
MyAvatar.goToLocation(intersection.intersection, false, {x: 0, y: 0, z: 0, w: 1}, false);
|
||||||
HMD.centerUI();
|
HMD.centerUI();
|
||||||
|
MyAvatar.centerBody();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -543,12 +543,14 @@ function connectionRequestCompleted() { // Final result is in. Do effects.
|
||||||
// don't change state (so animation continues while gripped)
|
// don't change state (so animation continues while gripped)
|
||||||
// but do send a notification, by calling the slot that emits the signal for it
|
// but do send a notification, by calling the slot that emits the signal for it
|
||||||
Window.makeConnection(true, result.connection.new_connection ? "You and " + result.connection.username + " are now connected!" : result.connection.username);
|
Window.makeConnection(true, result.connection.new_connection ? "You and " + result.connection.username + " are now connected!" : result.connection.username);
|
||||||
|
UserActivityLogger.makeUserConnection(connectingId, true, result.connection.new_connection ? "new connection" : "already connected");
|
||||||
return;
|
return;
|
||||||
} // failed
|
} // failed
|
||||||
endHandshake();
|
endHandshake();
|
||||||
debug("failing with result data", result);
|
debug("failing with result data", result);
|
||||||
// IWBNI we also did some fail sound/visual effect.
|
// IWBNI we also did some fail sound/visual effect.
|
||||||
Window.makeConnection(false, result.connection);
|
Window.makeConnection(false, result.connection);
|
||||||
|
UserActivityLogger.makeUserConnection(connectingId, false, result.connection);
|
||||||
}
|
}
|
||||||
var POLL_INTERVAL_MS = 200, POLL_LIMIT = 5;
|
var POLL_INTERVAL_MS = 200, POLL_LIMIT = 5;
|
||||||
function handleConnectionResponseAndMaybeRepeat(error, response) {
|
function handleConnectionResponseAndMaybeRepeat(error, response) {
|
||||||
|
@ -573,6 +575,7 @@ function handleConnectionResponseAndMaybeRepeat(error, response) {
|
||||||
} else if (error || (response.status !== 'success')) {
|
} else if (error || (response.status !== 'success')) {
|
||||||
debug('server fail', error, response.status);
|
debug('server fail', error, response.status);
|
||||||
result = error ? {status: 'error', connection: error} : response;
|
result = error ? {status: 'error', connection: error} : response;
|
||||||
|
UserActivityLogger.makeUserConnection(connectingId, false, error || response);
|
||||||
connectionRequestCompleted();
|
connectionRequestCompleted();
|
||||||
} else {
|
} else {
|
||||||
debug('server success', result);
|
debug('server success', result);
|
||||||
|
|
|
@ -269,13 +269,26 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See
|
||||||
getConnectionData();
|
getConnectionData();
|
||||||
UserActivityLogger.palAction("refresh_connections", "");
|
UserActivityLogger.palAction("refresh_connections", "");
|
||||||
break;
|
break;
|
||||||
|
case 'removeConnection':
|
||||||
|
connectionUserName = message.params;
|
||||||
|
request({
|
||||||
|
uri: METAVERSE_BASE + '/api/v1/user/connections/' + connectionUserName,
|
||||||
|
method: 'DELETE'
|
||||||
|
}, function (error, response) {
|
||||||
|
if (error || (response.status !== 'success')) {
|
||||||
|
print("Error: unable to remove connection", connectionUserName, error || response.status);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
getConnectionData();
|
||||||
|
});
|
||||||
|
break
|
||||||
|
|
||||||
case 'removeFriend':
|
case 'removeFriend':
|
||||||
friendUserName = message.params;
|
friendUserName = message.params;
|
||||||
request({
|
request({
|
||||||
uri: METAVERSE_BASE + '/api/v1/user/friends/' + friendUserName,
|
uri: METAVERSE_BASE + '/api/v1/user/friends/' + friendUserName,
|
||||||
method: 'DELETE'
|
method: 'DELETE'
|
||||||
}, function (error, response) {
|
}, function (error, response) {
|
||||||
print(JSON.stringify(response));
|
|
||||||
if (error || (response.status !== 'success')) {
|
if (error || (response.status !== 'success')) {
|
||||||
print("Error: unable to unfriend", friendUserName, error || response.status);
|
print("Error: unable to unfriend", friendUserName, error || response.status);
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in a new issue