Move Slider

This commit is contained in:
vladest 2017-12-28 15:39:22 +01:00
commit 2fbd0a41b1
188 changed files with 1844 additions and 1685 deletions

27
BUILD_LINUX_CHEATSHEET.md Normal file
View file

@ -0,0 +1,27 @@
# this guide is specific to Ubuntu 16.04.
# deb packages of High Fidelity domain server and assignment client are stored on debian.highfidelity.com
sudo su -
apt-get -y update
apt-get install -y software-properties-common
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 15FF1AAE
add-apt-repository "deb http://debian.highfidelity.com stable main"
apt-get -y update
apt-get install -y hifi-domain-server
apt-get install -y hifi-assignment-client
# When installing master/dev builds, the packages are slightly different and you just need to change the last 2 steps to:
apt-get install -y hifi-dev-domain-server
apt-get install -y hifi-dev-assignment-client
# domain server and assignment clients should already be running. The processes are controlled via:
systemctl start hifi-domain-server
systemctl stop hifi-domain-server
# Once the machine is setup and processes are running you should ensure that your firewall exposes port 40100 on TCP and all UDP ports. This will get your domain up and running and you could connect to it (for now) by using High Fidelity Interface and typing in the IP for the place name. (further customizations can be done via http://IPAddress:40100).
# The server always depends on both hifi-domain-server and hifi-assignment-client running at the same time.
# As an additional step, you should ensure that your packages are automatically updated when a new version goes out. You could, for example, set the automatic update checks to happen every hour (though this could potentially result in the domain being unreachable for a whole hour by new clients when they are released - adjust the update checks accordingly).
To do this you can modify /etc/crontab by adding the following lines
0 */1 * * * root apt-get update
1 */1 * * * root apt-get install --only-upgrade -y hifi-domain-server
2 */1 * * * root apt-get install --only-upgrade -y hifi-assignment-client

View file

@ -46,8 +46,14 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) :
const QCommandLineOption helpOption = parser.addHelpOption(); const QCommandLineOption helpOption = parser.addHelpOption();
const QCommandLineOption clientTypeOption(ASSIGNMENT_TYPE_OVERRIDE_OPTION, QString typeDescription = "run single assignment client of given type\n# | Type\n============================";
"run single assignment client of given type", "type"); for (Assignment::Type type = Assignment::FirstType;
type != Assignment::AllTypes;
type = static_cast<Assignment::Type>(static_cast<int>(type) + 1)) {
typeDescription.append(QStringLiteral("\n%1 | %2").arg(QString::number(type), Assignment::typeToString(type)));
}
const QCommandLineOption clientTypeOption(ASSIGNMENT_TYPE_OVERRIDE_OPTION, typeDescription, "type");
parser.addOption(clientTypeOption); parser.addOption(clientTypeOption);
const QCommandLineOption poolOption(ASSIGNMENT_POOL_OPTION, "set assignment pool", "pool-name"); const QCommandLineOption poolOption(ASSIGNMENT_POOL_OPTION, "set assignment pool", "pool-name");

View file

@ -214,7 +214,7 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
uint64_t getTimestamp() const override { uint64_t getTimestamp() const override {
return _lastEncodeTime; return _lastEncodeTime;
} }
const AvatarSharedPointer& getAvatar() const { return _avatar; } AvatarSharedPointer getAvatar() const { return _avatar; }
private: private:
AvatarSharedPointer _avatar; AvatarSharedPointer _avatar;
@ -326,7 +326,7 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
int remainingAvatars = (int)sortedAvatars.size(); int remainingAvatars = (int)sortedAvatars.size();
while (!sortedAvatars.empty()) { while (!sortedAvatars.empty()) {
const auto& avatarData = sortedAvatars.top().getAvatar(); const auto avatarData = sortedAvatars.top().getAvatar();
sortedAvatars.pop(); sortedAvatars.pop();
remainingAvatars--; remainingAvatars--;

View file

@ -945,7 +945,7 @@ void DomainServer::createStaticAssignmentsForType(Assignment::Type type, const Q
void DomainServer::populateDefaultStaticAssignmentsExcludingTypes(const QSet<Assignment::Type>& excludedTypes) { void DomainServer::populateDefaultStaticAssignmentsExcludingTypes(const QSet<Assignment::Type>& excludedTypes) {
// enumerate over all assignment types and see if we've already excluded it // enumerate over all assignment types and see if we've already excluded it
for (Assignment::Type defaultedType = Assignment::AudioMixerType; for (Assignment::Type defaultedType = Assignment::FirstType;
defaultedType != Assignment::AllTypes; defaultedType != Assignment::AllTypes;
defaultedType = static_cast<Assignment::Type>(static_cast<int>(defaultedType) + 1)) { defaultedType = static_cast<Assignment::Type>(static_cast<int>(defaultedType) + 1)) {
if (!excludedTypes.contains(defaultedType) && defaultedType != Assignment::AgentType) { if (!excludedTypes.contains(defaultedType) && defaultedType != Assignment::AgentType) {

View file

@ -12,8 +12,10 @@ function(JOIN VALUES GLUE OUTPUT)
endfunction() endfunction()
set(INTERFACE_QML_QRC ${CMAKE_CURRENT_BINARY_DIR}/qml.qrc) if (NOT DEV_BUILD)
generate_qrc(OUTPUT ${INTERFACE_QML_QRC} PATH ${CMAKE_CURRENT_SOURCE_DIR}/resources GLOBS *.qml *.qss *.js *.html *.ttf *.gif *.svg *.png *.jpg) set(INTERFACE_QML_QRC ${CMAKE_CURRENT_BINARY_DIR}/qml.qrc)
generate_qrc(OUTPUT ${INTERFACE_QML_QRC} PATH ${CMAKE_CURRENT_SOURCE_DIR}/resources GLOBS *.qml *.qss *.js *.html *.ttf *.gif *.svg *.png *.jpg)
endif()
# set a default root dir for each of our optional externals if it was not passed # set a default root dir for each of our optional externals if it was not passed
set(OPTIONAL_EXTERNALS "LeapMotion") set(OPTIONAL_EXTERNALS "LeapMotion")
@ -80,7 +82,9 @@ qt5_wrap_ui(QT_UI_HEADERS "${QT_UI_FILES}")
# add them to the interface source files # add them to the interface source files
set(INTERFACE_SRCS ${INTERFACE_SRCS} "${QT_UI_HEADERS}" "${QT_RESOURCES}") set(INTERFACE_SRCS ${INTERFACE_SRCS} "${QT_UI_HEADERS}" "${QT_RESOURCES}")
if (NOT DEV_BUILD)
list(APPEND INTERFACE_SRCS ${INTERFACE_QML_QRC}) list(APPEND INTERFACE_SRCS ${INTERFACE_QML_QRC})
endif()
if (UNIX) if (UNIX)
install( install(

View file

@ -0,0 +1,18 @@
import QtQuick 2.5
import QtQuick.Controls 1.4
Rectangle {
width: 100
height: 100
color: "white"
Rectangle {
width: 10
height: 10
color: "red"
}
Label {
text: OverlayWindowTestString
anchors.centerIn: parent
}
}

View file

@ -17,7 +17,6 @@ Windows.Window {
// Don't destroy on close... otherwise the JS/C++ will have a dangling pointer // Don't destroy on close... otherwise the JS/C++ will have a dangling pointer
destroyOnCloseButton: false destroyOnCloseButton: false
property var source; property var source;
property var component;
property var dynamicContent; property var dynamicContent;
// Keyboard control properties in case needed by QML content. // Keyboard control properties in case needed by QML content.
@ -30,28 +29,9 @@ Windows.Window {
dynamicContent.destroy(); dynamicContent.destroy();
dynamicContent = null; dynamicContent = null;
} }
component = Qt.createComponent(source); QmlSurface.load(source, contentHolder, function(newObject) {
console.log("Created component " + component + " from source " + source); dynamicContent = newObject;
} });
onComponentChanged: {
console.log("Component changed to " + component)
populate();
}
function populate() {
console.log("Populate called: dynamicContent " + dynamicContent + " component " + component);
if (!dynamicContent && component) {
if (component.status == Component.Error) {
console.log("Error loading component:", component.errorString());
} else if (component.status == Component.Ready) {
console.log("Building dynamic content");
dynamicContent = component.createObject(contentHolder);
} else {
console.log("Component not yet ready, connecting to status change");
component.statusChanged.connect(populate);
}
}
} }
// Handle message traffic from the script that launched us to the loaded QML // Handle message traffic from the script that launched us to the loaded QML

View file

@ -30,7 +30,7 @@ Original.Button {
onHoveredChanged: { onHoveredChanged: {
if (hovered) { if (hovered) {
tabletInterface.playSound(TabletEnums.ButtonHover); Tablet.playSound(TabletEnums.ButtonHover);
} }
} }
@ -41,7 +41,7 @@ Original.Button {
} }
onClicked: { onClicked: {
tabletInterface.playSound(TabletEnums.ButtonClick); Tablet.playSound(TabletEnums.ButtonClick);
if (action !== null) { if (action !== null) {
action.triggered() action.triggered()
} }

View file

@ -31,7 +31,7 @@ Original.CheckBox {
hoverEnabled: true hoverEnabled: true
onClicked: { onClicked: {
tabletInterface.playSound(TabletEnums.ButtonClick); Tablet.playSound(TabletEnums.ButtonClick);
} }
onHoveredChanged: { onHoveredChanged: {

View file

@ -36,12 +36,12 @@ CheckBox {
hoverEnabled: true hoverEnabled: true
onClicked: { onClicked: {
tabletInterface.playSound(TabletEnums.ButtonClick); Tablet.playSound(TabletEnums.ButtonClick);
} }
onHoveredChanged: { onHoveredChanged: {
if (hovered) { if (hovered) {
tabletInterface.playSound(TabletEnums.ButtonHover); Tablet.playSound(TabletEnums.ButtonHover);
} }
} }

View file

@ -28,7 +28,7 @@ Original.Button {
onHoveredChanged: { onHoveredChanged: {
if (hovered) { if (hovered) {
tabletInterface.playSound(TabletEnums.ButtonHover); Tablet.playSound(TabletEnums.ButtonHover);
} }
} }
onActionChanged: { onActionChanged: {
@ -38,7 +38,7 @@ Original.Button {
} }
onClicked: { onClicked: {
tabletInterface.playSound(TabletEnums.ButtonClick); Tablet.playSound(TabletEnums.ButtonClick);
if (action !== null) { if (action !== null) {
action.triggered() action.triggered()
} }

View file

@ -41,13 +41,13 @@ Item {
onContainsMouseChanged: { onContainsMouseChanged: {
if (containsMouse) { if (containsMouse) {
tabletInterface.playSound(TabletEnums.ButtonHover); Tablet.playSound(TabletEnums.ButtonHover);
} }
} }
onClicked: { onClicked: {
mouse.accepted = true; mouse.accepted = true;
tabletInterface.playSound(TabletEnums.ButtonClick); Tablet.playSound(TabletEnums.ButtonClick);
webEntity.synthesizeKeyPress(glyph); webEntity.synthesizeKeyPress(glyph);
webEntity.synthesizeKeyPress(glyph, mirrorText); webEntity.synthesizeKeyPress(glyph, mirrorText);

View file

@ -31,7 +31,7 @@ Original.RadioButton {
readonly property int checkRadius: 2 readonly property int checkRadius: 2
onClicked: { onClicked: {
tabletInterface.playSound(TabletEnums.ButtonClick); Tablet.playSound(TabletEnums.ButtonClick);
} }
onHoveredChanged: { onHoveredChanged: {

View file

@ -22,28 +22,27 @@ Slider {
property string label: "" property string label: ""
property real controlHeight: height + (sliderLabel.visible ? sliderLabel.height + sliderLabel.anchors.bottomMargin : 0) property real controlHeight: height + (sliderLabel.visible ? sliderLabel.height + sliderLabel.anchors.bottomMargin : 0)
property alias minimumValue: slider.from
property alias maximumValue: slider.to
height: hifi.fontSizes.textFieldInput + 14 // Match height of TextField control. height: hifi.fontSizes.textFieldInput + 14 // Match height of TextField control.
y: sliderLabel.visible ? sliderLabel.height + sliderLabel.anchors.bottomMargin : 0 y: sliderLabel.visible ? sliderLabel.height + sliderLabel.anchors.bottomMargin : 0
background: Rectangle { background: Rectangle {
x: slider.leftPadding
y: slider.topPadding + slider.availableHeight / 2 - height / 2
implicitWidth: 50 implicitWidth: 50
implicitHeight: hifi.dimensions.sliderGrooveHeight implicitHeight: hifi.dimensions.sliderGrooveHeight
width: slider.availableWidth
height: implicitHeight
radius: height / 2 radius: height / 2
color: isLightColorScheme ? hifi.colors.sliderGutterLight : hifi.colors.sliderGutterDark color: isLightColorScheme ? hifi.colors.sliderGutterLight : hifi.colors.sliderGutterDark
Rectangle { Rectangle {
width: parent.height - 2 width: slider.visualPosition * parent.width
height: slider.width * (slider.value - slider.minimumValue) / (slider.maximumValue - slider.minimumValue) - 1 height: parent.height
radius: height / 2 radius: height / 2
anchors {
top: parent.top
topMargin: width + 1
left: parent.left
leftMargin: 1
}
transformOrigin: Item.TopLeft
rotation: -90
gradient: Gradient { gradient: Gradient {
GradientStop { position: 0.0; color: hifi.colors.blueAccent } GradientStop { position: 0.0; color: hifi.colors.blueAccent }
GradientStop { position: 1.0; color: hifi.colors.primaryHighlight } GradientStop { position: 1.0; color: hifi.colors.primaryHighlight }

View file

@ -49,7 +49,7 @@ Item {
} }
if (WebEngineView.LoadFailedStatus === loadRequest.status) { if (WebEngineView.LoadFailedStatus === loadRequest.status) {
console.log(" Tablet WebEngineView failed to load url: " + loadRequest.url.toString()); console.log("Tablet WebEngineView failed to load url: " + loadRequest.url.toString());
} }
if (WebEngineView.LoadSucceededStatus === loadRequest.status) { if (WebEngineView.LoadSucceededStatus === loadRequest.status) {

View file

@ -25,13 +25,13 @@ Preference {
id: button id: button
onHoveredChanged: { onHoveredChanged: {
if (hovered) { if (hovered) {
tabletInterface.playSound(TabletEnums.ButtonHover); Tablet.playSound(TabletEnums.ButtonHover);
} }
} }
onClicked: { onClicked: {
preference.trigger(); preference.trigger();
tabletInterface.playSound(TabletEnums.ButtonClick); Tablet.playSound(TabletEnums.ButtonClick);
} }
width: 180 width: 180
anchors.bottom: parent.bottom anchors.bottom: parent.bottom

View file

@ -41,12 +41,12 @@ Preference {
id: checkBox id: checkBox
onHoveredChanged: { onHoveredChanged: {
if (hovered) { if (hovered) {
tabletInterface.playSound(TabletEnums.ButtonHover); Tablet.playSound(TabletEnums.ButtonHover);
} }
} }
onClicked: { onClicked: {
tabletInterface.playSound(TabletEnums.ButtonClick); Tablet.playSound(TabletEnums.ButtonClick);
} }
anchors { anchors {

View file

@ -246,12 +246,12 @@ Item {
anchors.fill: parent; anchors.fill: parent;
acceptedButtons: Qt.LeftButton; acceptedButtons: Qt.LeftButton;
onClicked: { onClicked: {
tabletInterface.playSound(TabletEnums.ButtonClick); Tablet.playSound(TabletEnums.ButtonClick);
goFunction("hifi://" + hifiUrl); goFunction("hifi://" + hifiUrl);
} }
hoverEnabled: true; hoverEnabled: true;
onEntered: { onEntered: {
tabletInterface.playSound(TabletEnums.ButtonHover); Tablet.playSound(TabletEnums.ButtonHover);
hoverThunk(); hoverThunk();
} }
onExited: unhoverThunk(); onExited: unhoverThunk();
@ -269,7 +269,7 @@ Item {
} }
} }
function go() { function go() {
tabletInterface.playSound(TabletEnums.ButtonClick); Tablet.playSound(TabletEnums.ButtonClick);
goFunction(drillDownToPlace ? ("/places/" + placeName) : ("/user_stories/" + storyId)); goFunction(drillDownToPlace ? ("/places/" + placeName) : ("/user_stories/" + storyId));
} }
MouseArea { MouseArea {

View file

@ -45,11 +45,13 @@ OriginalDesktop.Desktop {
Toolbar { Toolbar {
id: sysToolbar; id: sysToolbar;
objectName: "com.highfidelity.interface.toolbar.system"; objectName: "com.highfidelity.interface.toolbar.system";
property var tablet: Tablet.getTablet("com.highfidelity.interface.tablet.system");
anchors.horizontalCenter: settings.constrainToolbarToCenterX ? desktop.horizontalCenter : undefined; anchors.horizontalCenter: settings.constrainToolbarToCenterX ? desktop.horizontalCenter : undefined;
// Literal 50 is overwritten by settings from previous session, and sysToolbar.x comes from settings when not constrained. // Literal 50 is overwritten by settings from previous session, and sysToolbar.x comes from settings when not constrained.
x: sysToolbar.x x: sysToolbar.x
y: 50 y: 50
shown: true buttonModel: tablet.buttons;
shown: tablet.toolbarMode;
} }
Settings { Settings {

View file

@ -59,12 +59,12 @@ Rectangle {
scrollGestureEnabled: false; scrollGestureEnabled: false;
onClicked: { onClicked: {
Audio.muted = !Audio.muted; Audio.muted = !Audio.muted;
tabletInterface.playSound(TabletEnums.ButtonClick); Tablet.playSound(TabletEnums.ButtonClick);
} }
drag.target: dragTarget; drag.target: dragTarget;
onContainsMouseChanged: { onContainsMouseChanged: {
if (containsMouse) { if (containsMouse) {
tabletInterface.playSound(TabletEnums.ButtonHover); Tablet.playSound(TabletEnums.ButtonHover);
} }
} }
} }

View file

@ -33,6 +33,7 @@ Rectangle {
property string itemName; property string itemName;
property string itemId; property string itemId;
property string itemHref; property string itemHref;
property string itemAuthor;
property double balanceAfterPurchase; property double balanceAfterPurchase;
property bool alreadyOwned: false; property bool alreadyOwned: false;
property int itemPrice: -1; property int itemPrice: -1;
@ -41,10 +42,11 @@ Rectangle {
property bool debugCheckoutSuccess: false; property bool debugCheckoutSuccess: false;
property bool canRezCertifiedItems: Entities.canRezCertified() || Entities.canRezTmpCertified(); property bool canRezCertifiedItems: Entities.canRezCertified() || Entities.canRezTmpCertified();
property bool isWearable; property bool isWearable;
property string referrer;
// Style // Style
color: hifi.colors.white; color: hifi.colors.white;
Hifi.QmlCommerce { Connections {
id: commerce; target: Commerce;
onWalletStatusResult: { onWalletStatusResult: {
if (walletStatus === 0) { if (walletStatus === 0) {
@ -59,6 +61,7 @@ Rectangle {
} else if (walletStatus === 2) { } else if (walletStatus === 2) {
if (root.activeView !== "passphraseModal") { if (root.activeView !== "passphraseModal") {
root.activeView = "passphraseModal"; root.activeView = "passphraseModal";
UserActivityLogger.commercePassphraseEntry("marketplace checkout");
} }
} else if (walletStatus === 3) { } else if (walletStatus === 3) {
authSuccessStep(); authSuccessStep();
@ -71,7 +74,7 @@ Rectangle {
if (!isLoggedIn && root.activeView !== "needsLogIn") { if (!isLoggedIn && root.activeView !== "needsLogIn") {
root.activeView = "needsLogIn"; root.activeView = "needsLogIn";
} else { } else {
commerce.getWalletStatus(); Commerce.getWalletStatus();
} }
} }
@ -79,12 +82,12 @@ Rectangle {
if (result.status !== 'success') { if (result.status !== 'success') {
failureErrorText.text = result.message; failureErrorText.text = result.message;
root.activeView = "checkoutFailure"; root.activeView = "checkoutFailure";
UserActivityLogger.commercePurchaseFailure(root.itemId, root.itemPrice, !root.alreadyOwned, result.message); UserActivityLogger.commercePurchaseFailure(root.itemId, root.itemAuthor, root.itemPrice, !root.alreadyOwned, result.message);
} else { } else {
root.itemHref = result.data.download_url; root.itemHref = result.data.download_url;
root.isWearable = result.data.categories.indexOf("Wearables") > -1; root.isWearable = result.data.categories.indexOf("Wearables") > -1;
root.activeView = "checkoutSuccess"; root.activeView = "checkoutSuccess";
UserActivityLogger.commercePurchaseSuccess(root.itemId, root.itemPrice, !root.alreadyOwned); UserActivityLogger.commercePurchaseSuccess(root.itemId, root.itemAuthor, root.itemPrice, !root.alreadyOwned);
} }
} }
@ -114,7 +117,7 @@ Rectangle {
} }
onItemIdChanged: { onItemIdChanged: {
commerce.inventory(); Commerce.inventory();
itemPreviewImage.source = "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/" + itemId + "/thumbnail/hifi-mp-" + itemId + ".jpg"; itemPreviewImage.source = "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/" + itemId + "/thumbnail/hifi-mp-" + itemId + ".jpg";
} }
@ -123,14 +126,14 @@ Rectangle {
} }
onItemPriceChanged: { onItemPriceChanged: {
commerce.balance(); Commerce.balance();
} }
Timer { Timer {
id: notSetUpTimer; id: notSetUpTimer;
interval: 200; interval: 200;
onTriggered: { onTriggered: {
sendToScript({method: 'checkout_walletNotSetUp', itemId: itemId}); sendToScript({method: 'checkout_walletNotSetUp', itemId: itemId, referrer: referrer});
} }
} }
@ -202,7 +205,7 @@ Rectangle {
Component.onCompleted: { Component.onCompleted: {
purchasesReceived = false; purchasesReceived = false;
balanceReceived = false; balanceReceived = false;
commerce.getWalletStatus(); Commerce.getWalletStatus();
} }
} }
@ -223,7 +226,7 @@ Rectangle {
Connections { Connections {
target: GlobalServices target: GlobalServices
onMyUsernameChanged: { onMyUsernameChanged: {
commerce.getLoginStatus(); Commerce.getLoginStatus();
} }
} }
@ -408,7 +411,8 @@ Rectangle {
Rectangle { Rectangle {
id: buyTextContainer; id: buyTextContainer;
visible: buyText.text !== ""; visible: buyText.text !== "";
anchors.top: parent.top; anchors.top: cancelPurchaseButton.bottom;
anchors.topMargin: 16;
anchors.left: parent.left; anchors.left: parent.left;
anchors.right: parent.right; anchors.right: parent.right;
height: buyText.height + 30; height: buyText.height + 30;
@ -463,8 +467,8 @@ Rectangle {
enabled: (root.balanceAfterPurchase >= 0 && purchasesReceived && balanceReceived) || !itemIsJson; enabled: (root.balanceAfterPurchase >= 0 && purchasesReceived && balanceReceived) || !itemIsJson;
color: hifi.buttons.blue; color: hifi.buttons.blue;
colorScheme: hifi.colorSchemes.light; colorScheme: hifi.colorSchemes.light;
anchors.top: buyTextContainer.visible ? buyTextContainer.bottom : checkoutActionButtonsContainer.top; anchors.top: checkoutActionButtonsContainer.top;
anchors.topMargin: buyTextContainer.visible ? 12 : 16; anchors.topMargin: 16;
height: 40; height: 40;
anchors.left: parent.left; anchors.left: parent.left;
anchors.right: parent.right; anchors.right: parent.right;
@ -473,9 +477,9 @@ Rectangle {
if (itemIsJson) { if (itemIsJson) {
buyButton.enabled = false; buyButton.enabled = false;
if (!root.shouldBuyWithControlledFailure) { if (!root.shouldBuyWithControlledFailure) {
commerce.buy(itemId, itemPrice); Commerce.buy(itemId, itemPrice);
} else { } else {
commerce.buy(itemId, itemPrice, true); Commerce.buy(itemId, itemPrice, true);
} }
} else { } else {
if (urlHandler.canHandleUrl(itemHref)) { if (urlHandler.canHandleUrl(itemHref)) {
@ -876,6 +880,8 @@ Rectangle {
itemName = message.params.itemName; itemName = message.params.itemName;
root.itemPrice = message.params.itemPrice; root.itemPrice = message.params.itemPrice;
itemHref = message.params.itemHref; itemHref = message.params.itemHref;
referrer = message.params.referrer;
itemAuthor = message.params.itemAuthor;
setBuyText(); setBuyText();
break; break;
default: default:
@ -923,11 +929,11 @@ Rectangle {
buyText.text = ""; buyText.text = "";
} }
} else { } else {
buyText.text = "This free item <b>will not</b> be added to your <b>Purchases</b>. Non-entities can't yet be purchased for HFC."; buyText.text = '<i>This type of item cannot currently be certified, so it will not show up in "My Purchases". You can access it again for free from the Marketplace.</i>';
buyTextContainer.color = "#FFD6AD"; buyTextContainer.color = hifi.colors.white;
buyTextContainer.border.color = "#FAC07D"; buyTextContainer.border.color = hifi.colors.white;
buyGlyph.text = hifi.glyphs.alert; buyGlyph.text = "";
buyGlyph.size = 46; buyGlyph.size = 0;
} }
} }
@ -939,8 +945,8 @@ Rectangle {
} }
root.balanceReceived = false; root.balanceReceived = false;
root.purchasesReceived = false; root.purchasesReceived = false;
commerce.inventory(); Commerce.inventory();
commerce.balance(); Commerce.balance();
} }
// //

View file

@ -30,14 +30,14 @@ Item {
height: mainContainer.height + additionalDropdownHeight; height: mainContainer.height + additionalDropdownHeight;
Hifi.QmlCommerce { Connections {
id: commerce; target: Commerce;
onWalletStatusResult: { onWalletStatusResult: {
if (walletStatus === 0) { if (walletStatus === 0) {
sendToParent({method: "needsLogIn"}); sendToParent({method: "needsLogIn"});
} else if (walletStatus === 3) { } else if (walletStatus === 3) {
commerce.getSecurityImage(); Commerce.getSecurityImage();
} else if (walletStatus > 3) { } else if (walletStatus > 3) {
console.log("ERROR in EmulatedMarketplaceHeader.qml: Unknown wallet status: " + walletStatus); console.log("ERROR in EmulatedMarketplaceHeader.qml: Unknown wallet status: " + walletStatus);
} }
@ -47,7 +47,7 @@ Item {
if (!isLoggedIn) { if (!isLoggedIn) {
sendToParent({method: "needsLogIn"}); sendToParent({method: "needsLogIn"});
} else { } else {
commerce.getWalletStatus(); Commerce.getWalletStatus();
} }
} }
@ -60,13 +60,13 @@ Item {
} }
Component.onCompleted: { Component.onCompleted: {
commerce.getWalletStatus(); Commerce.getWalletStatus();
} }
Connections { Connections {
target: GlobalServices target: GlobalServices
onMyUsernameChanged: { onMyUsernameChanged: {
commerce.getLoginStatus(); Commerce.getLoginStatus();
} }
} }

View file

@ -35,8 +35,8 @@ Rectangle {
property bool isCertificateInvalid: false; property bool isCertificateInvalid: false;
// Style // Style
color: hifi.colors.faintGray; color: hifi.colors.faintGray;
Hifi.QmlCommerce { Connections {
id: commerce; target: Commerce;
onCertificateInfoResult: { onCertificateInfoResult: {
if (result.status !== 'success') { if (result.status !== 'success') {
@ -108,7 +108,7 @@ Rectangle {
onCertificateIdChanged: { onCertificateIdChanged: {
if (certificateId !== "") { if (certificateId !== "") {
commerce.certificateInfo(certificateId); Commerce.certificateInfo(certificateId);
} }
} }

View file

@ -37,8 +37,8 @@ Rectangle {
property bool isDebuggingFirstUseTutorial: false; property bool isDebuggingFirstUseTutorial: false;
// Style // Style
color: hifi.colors.white; color: hifi.colors.white;
Hifi.QmlCommerce { Connections {
id: commerce; target: Commerce;
onWalletStatusResult: { onWalletStatusResult: {
if (walletStatus === 0) { if (walletStatus === 0) {
@ -53,13 +53,14 @@ Rectangle {
} else if (walletStatus === 2) { } else if (walletStatus === 2) {
if (root.activeView !== "passphraseModal") { if (root.activeView !== "passphraseModal") {
root.activeView = "passphraseModal"; root.activeView = "passphraseModal";
UserActivityLogger.commercePassphraseEntry("marketplace purchases");
} }
} else if (walletStatus === 3) { } else if (walletStatus === 3) {
if ((Settings.getValue("isFirstUseOfPurchases", true) || root.isDebuggingFirstUseTutorial) && root.activeView !== "firstUseTutorial") { if ((Settings.getValue("isFirstUseOfPurchases", true) || root.isDebuggingFirstUseTutorial) && root.activeView !== "firstUseTutorial") {
root.activeView = "firstUseTutorial"; root.activeView = "firstUseTutorial";
} else if (!Settings.getValue("isFirstUseOfPurchases", true) && root.activeView === "initialize") { } else if (!Settings.getValue("isFirstUseOfPurchases", true) && root.activeView === "initialize") {
root.activeView = "purchasesMain"; root.activeView = "purchasesMain";
commerce.inventory(); Commerce.inventory();
} }
} else { } else {
console.log("ERROR in Purchases.qml: Unknown wallet status: " + walletStatus); console.log("ERROR in Purchases.qml: Unknown wallet status: " + walletStatus);
@ -70,7 +71,7 @@ Rectangle {
if (!isLoggedIn && root.activeView !== "needsLogIn") { if (!isLoggedIn && root.activeView !== "needsLogIn") {
root.activeView = "needsLogIn"; root.activeView = "needsLogIn";
} else { } else {
commerce.getWalletStatus(); Commerce.getWalletStatus();
} }
} }
@ -196,7 +197,7 @@ Rectangle {
Component.onCompleted: { Component.onCompleted: {
securityImageResultReceived = false; securityImageResultReceived = false;
purchasesReceived = false; purchasesReceived = false;
commerce.getWalletStatus(); Commerce.getWalletStatus();
} }
} }
@ -217,7 +218,7 @@ Rectangle {
Connections { Connections {
target: GlobalServices target: GlobalServices
onMyUsernameChanged: { onMyUsernameChanged: {
commerce.getLoginStatus(); Commerce.getLoginStatus();
} }
} }
@ -232,7 +233,7 @@ Rectangle {
onSendSignalToParent: { onSendSignalToParent: {
if (msg.method === "authSuccess") { if (msg.method === "authSuccess") {
root.activeView = "initialize"; root.activeView = "initialize";
commerce.getWalletStatus(); Commerce.getWalletStatus();
} else { } else {
sendToScript(msg); sendToScript(msg);
} }
@ -253,7 +254,7 @@ Rectangle {
case 'tutorial_finished': case 'tutorial_finished':
Settings.setValue("isFirstUseOfPurchases", false); Settings.setValue("isFirstUseOfPurchases", false);
root.activeView = "purchasesMain"; root.activeView = "purchasesMain";
commerce.inventory(); Commerce.inventory();
break; break;
} }
} }
@ -593,7 +594,7 @@ Rectangle {
if (root.activeView === "purchasesMain" && !root.pendingInventoryReply) { if (root.activeView === "purchasesMain" && !root.pendingInventoryReply) {
console.log("Refreshing Purchases..."); console.log("Refreshing Purchases...");
root.pendingInventoryReply = true; root.pendingInventoryReply = true;
commerce.inventory(); Commerce.inventory();
} }
} }
} }

View file

@ -27,8 +27,8 @@ Item {
property string keyFilePath; property string keyFilePath;
property bool showDebugButtons: true; property bool showDebugButtons: true;
Hifi.QmlCommerce { Connections {
id: commerce; target: Commerce;
onKeyFilePathIfExistsResult: { onKeyFilePathIfExistsResult: {
root.keyFilePath = path; root.keyFilePath = path;
@ -37,7 +37,7 @@ Item {
onVisibleChanged: { onVisibleChanged: {
if (visible) { if (visible) {
commerce.getKeyFilePathIfExists(); Commerce.getKeyFilePathIfExists();
} }
} }
@ -55,6 +55,37 @@ Item {
// Style // Style
color: hifi.colors.blueHighlight; color: hifi.colors.blueHighlight;
} }
HifiControlsUit.Button {
id: clearCachedPassphraseButton;
visible: root.showDebugButtons;
color: hifi.buttons.black;
colorScheme: hifi.colorSchemes.dark;
anchors.top: parent.top;
anchors.left: helpTitleText.right;
anchors.leftMargin: 20;
height: 40;
width: 150;
text: "DBG: Clear Pass";
onClicked: {
Commerce.setPassphrase("");
sendSignalToWallet({method: 'passphraseReset'});
}
}
HifiControlsUit.Button {
id: resetButton;
visible: root.showDebugButtons;
color: hifi.buttons.red;
colorScheme: hifi.colorSchemes.dark;
anchors.top: clearCachedPassphraseButton.top;
anchors.left: clearCachedPassphraseButton.right;
height: 40;
width: 150;
text: "DBG: RST Wallet";
onClicked: {
Commerce.reset();
sendSignalToWallet({method: 'walletReset'});
}
}
ListModel { ListModel {
id: helpModel; id: helpModel;

View file

@ -29,8 +29,8 @@ Item {
source: "images/wallet-bg.jpg"; source: "images/wallet-bg.jpg";
} }
Hifi.QmlCommerce { Connections {
id: commerce; target: Commerce;
} }
// //

View file

@ -24,10 +24,6 @@ Item {
id: root; id: root;
SecurityImageModel {
id: securityImageModel;
}
// Username Text // Username Text
RalewayRegular { RalewayRegular {
id: usernameText; id: usernameText;

View file

@ -35,8 +35,8 @@ Item {
source: "images/wallet-bg.jpg"; source: "images/wallet-bg.jpg";
} }
Hifi.QmlCommerce { Connections {
id: commerce; target: Commerce;
onSecurityImageResult: { onSecurityImageResult: {
titleBarSecurityImage.source = ""; titleBarSecurityImage.source = "";
@ -49,8 +49,12 @@ Item {
submitPassphraseInputButton.enabled = true; submitPassphraseInputButton.enabled = true;
if (!isAuthenticated) { if (!isAuthenticated) {
errorText.text = "Authentication failed - please try again."; errorText.text = "Authentication failed - please try again.";
passphraseField.error = true;
UserActivityLogger.commercePassphraseAuthenticationStatus("auth failure");
} else { } else {
sendSignalToParent({method: 'authSuccess'});; sendSignalToParent({method: 'authSuccess'});
passphraseField.error = false;
UserActivityLogger.commercePassphraseAuthenticationStatus("auth success");
} }
} }
} }
@ -69,6 +73,7 @@ Item {
// TODO: Fix this unlikely bug // TODO: Fix this unlikely bug
onVisibleChanged: { onVisibleChanged: {
if (visible) { if (visible) {
passphraseField.error = false;
passphraseField.focus = true; passphraseField.focus = true;
sendSignalToParent({method: 'disableHmdPreview'}); sendSignalToParent({method: 'disableHmdPreview'});
} else { } else {
@ -207,7 +212,7 @@ Item {
onAccepted: { onAccepted: {
submitPassphraseInputButton.enabled = false; submitPassphraseInputButton.enabled = false;
commerce.setPassphrase(passphraseField.text); Commerce.setPassphrase(passphraseField.text);
} }
} }
@ -247,7 +252,7 @@ Item {
source: "image://security/securityImage"; source: "image://security/securityImage";
cache: false; cache: false;
onVisibleChanged: { onVisibleChanged: {
commerce.getSecurityImage(); Commerce.getSecurityImage();
} }
} }
Item { Item {
@ -315,7 +320,7 @@ Item {
text: "Submit" text: "Submit"
onClicked: { onClicked: {
submitPassphraseInputButton.enabled = false; submitPassphraseInputButton.enabled = false;
commerce.setPassphrase(passphraseField.text); Commerce.setPassphrase(passphraseField.text);
} }
} }
@ -335,6 +340,7 @@ Item {
text: "Cancel" text: "Cancel"
onClicked: { onClicked: {
sendSignalToParent({method: 'passphrasePopup_cancelClicked'}); sendSignalToParent({method: 'passphrasePopup_cancelClicked'});
UserActivityLogger.commercePassphraseAuthenticationStatus("passphrase modal cancelled");
} }
} }
} }

View file

@ -35,8 +35,8 @@ Item {
propagateComposedEvents: false; propagateComposedEvents: false;
} }
Hifi.QmlCommerce { Connections {
id: commerce; target: Commerce;
onSecurityImageResult: { onSecurityImageResult: {
passphrasePageSecurityImage.source = ""; passphrasePageSecurityImage.source = "";
passphrasePageSecurityImage.source = "image://security/securityImage"; passphrasePageSecurityImage.source = "image://security/securityImage";
@ -53,6 +53,9 @@ Item {
// TODO: Fix this unlikely bug // TODO: Fix this unlikely bug
onVisibleChanged: { onVisibleChanged: {
if (visible) { if (visible) {
passphraseField.error = false;
passphraseFieldAgain.error = false;
currentPassphraseField.error = false;
if (root.shouldImmediatelyFocus) { if (root.shouldImmediatelyFocus) {
focusFirstTextField(); focusFirstTextField();
} }
@ -159,7 +162,7 @@ Item {
source: "image://security/securityImage"; source: "image://security/securityImage";
cache: false; cache: false;
onVisibleChanged: { onVisibleChanged: {
commerce.getSecurityImage(); Commerce.getSecurityImage();
} }
} }
Item { Item {
@ -282,7 +285,7 @@ Item {
passphraseFieldAgain.error = false; passphraseFieldAgain.error = false;
currentPassphraseField.error = false; currentPassphraseField.error = false;
setErrorText(""); setErrorText("");
commerce.changePassphrase(currentPassphraseField.text, passphraseField.text); Commerce.changePassphrase(currentPassphraseField.text, passphraseField.text);
return true; return true;
} }
} }

View file

@ -26,8 +26,8 @@ Item {
id: root; id: root;
property string keyFilePath; property string keyFilePath;
Hifi.QmlCommerce { Connections {
id: commerce; target: Commerce;
onKeyFilePathIfExistsResult: { onKeyFilePathIfExistsResult: {
root.keyFilePath = path; root.keyFilePath = path;
@ -233,7 +233,7 @@ Item {
onVisibleChanged: { onVisibleChanged: {
if (visible) { if (visible) {
commerce.getKeyFilePathIfExists(); Commerce.getKeyFilePathIfExists();
} }
} }

View file

@ -25,12 +25,8 @@ Item {
id: root; id: root;
property bool justSubmitted: false; property bool justSubmitted: false;
SecurityImageModel { Connections {
id: securityImageModel; target: Commerce;
}
Hifi.QmlCommerce {
id: commerce;
onSecurityImageResult: { onSecurityImageResult: {
securityImageChangePageSecurityImage.source = ""; securityImageChangePageSecurityImage.source = "";
@ -212,4 +208,8 @@ Item {
securityImageSubmitButton.enabled = true; securityImageSubmitButton.enabled = true;
securityImageSubmitButton.text = "Submit"; securityImageSubmitButton.text = "Submit";
} }
function initModel() {
securityImageSelection.initModel();
}
} }

View file

@ -15,29 +15,28 @@ import QtQuick 2.5
ListModel { ListModel {
id: root; id: root;
ListElement{
sourcePath: "images/01.jpg" function initModel() {
securityImageEnumValue: 1; var array = [];
while (array.length < 6) {
// We currently have 34 security images to choose from
var randomNumber = Math.floor(Math.random() * 34) + 1;
if (array.indexOf(randomNumber) > -1) {
continue;
}
array[array.length] = randomNumber;
}
var modelElement;
for (var i = 0; i < 6; i++) {
modelElement = { "sourcePath":"images/" + addLeadingZero(array[i]) + ".jpg", "securityImageEnumValue": (i + 1) }
root.insert(i, modelElement);
}
} }
ListElement{
sourcePath: "images/02.jpg" function addLeadingZero(n) {
securityImageEnumValue: 2; return n < 10 ? '0' + n : '' + n;
}
ListElement{
sourcePath: "images/03.jpg"
securityImageEnumValue: 3;
}
ListElement{
sourcePath: "images/04.jpg"
securityImageEnumValue: 4;
}
ListElement{
sourcePath: "images/05.jpg"
securityImageEnumValue: 5;
}
ListElement{
sourcePath: "images/06.jpg"
securityImageEnumValue: 6;
} }
function getImagePathFromImageID(imageID) { function getImagePathFromImageID(imageID) {

View file

@ -94,6 +94,10 @@ Item {
function getSelectedImageIndex() { function getSelectedImageIndex() {
return gridModel.get(securityImageGrid.currentIndex).securityImageEnumValue; return gridModel.get(securityImageGrid.currentIndex).securityImageEnumValue;
} }
function initModel() {
gridModel.initModel();
}
// //
// FUNCTION DEFINITIONS END // FUNCTION DEFINITIONS END
// //

View file

@ -24,8 +24,8 @@ Item {
id: root; id: root;
Hifi.QmlCommerce { Connections {
id: commerce; target: Commerce;
} }
// "Unavailable" // "Unavailable"

View file

@ -30,13 +30,15 @@ Rectangle {
property bool keyboardRaised: false; property bool keyboardRaised: false;
property bool isPassword: false; property bool isPassword: false;
anchors.fill: (typeof parent === undefined) ? undefined : parent;
Image { Image {
anchors.fill: parent; anchors.fill: parent;
source: "images/wallet-bg.jpg"; source: "images/wallet-bg.jpg";
} }
Hifi.QmlCommerce { Connections {
id: commerce; target: Commerce;
onWalletStatusResult: { onWalletStatusResult: {
if (walletStatus === 0) { if (walletStatus === 0) {
@ -46,7 +48,7 @@ Rectangle {
} else if (walletStatus === 1) { } else if (walletStatus === 1) {
if (root.activeView !== "walletSetup") { if (root.activeView !== "walletSetup") {
root.activeView = "walletSetup"; root.activeView = "walletSetup";
commerce.resetLocalWalletOnly(); Commerce.resetLocalWalletOnly();
var timestamp = new Date(); var timestamp = new Date();
walletSetup.startingTimestamp = timestamp; walletSetup.startingTimestamp = timestamp;
walletSetup.setupAttemptID = generateUUID(); walletSetup.setupAttemptID = generateUUID();
@ -56,10 +58,13 @@ Rectangle {
} else if (walletStatus === 2) { } else if (walletStatus === 2) {
if (root.activeView !== "passphraseModal") { if (root.activeView !== "passphraseModal") {
root.activeView = "passphraseModal"; root.activeView = "passphraseModal";
UserActivityLogger.commercePassphraseEntry("wallet app");
} }
} else if (walletStatus === 3) { } else if (walletStatus === 3) {
root.activeView = "walletHome"; if (root.activeView !== "walletSetup") {
commerce.getSecurityImage(); root.activeView = "walletHome";
Commerce.getSecurityImage();
}
} else { } else {
console.log("ERROR in Wallet.qml: Unknown wallet status: " + walletStatus); console.log("ERROR in Wallet.qml: Unknown wallet status: " + walletStatus);
} }
@ -69,7 +74,7 @@ Rectangle {
if (!isLoggedIn && root.activeView !== "needsLogIn") { if (!isLoggedIn && root.activeView !== "needsLogIn") {
root.activeView = "needsLogIn"; root.activeView = "needsLogIn";
} else if (isLoggedIn) { } else if (isLoggedIn) {
commerce.getWalletStatus(); Commerce.getWalletStatus();
} }
} }
@ -81,10 +86,6 @@ Rectangle {
} }
} }
SecurityImageModel {
id: securityImageModel;
}
HifiCommerceCommon.CommerceLightbox { HifiCommerceCommon.CommerceLightbox {
id: lightboxPopup; id: lightboxPopup;
visible: false; visible: false;
@ -179,7 +180,7 @@ Rectangle {
if (msg.method === 'walletSetup_finished') { if (msg.method === 'walletSetup_finished') {
if (msg.referrer === '' || msg.referrer === 'marketplace cta') { if (msg.referrer === '' || msg.referrer === 'marketplace cta') {
root.activeView = "initialize"; root.activeView = "initialize";
commerce.getWalletStatus(); Commerce.getWalletStatus();
} else if (msg.referrer === 'purchases') { } else if (msg.referrer === 'purchases') {
sendToScript({method: 'goToPurchases'}); sendToScript({method: 'goToPurchases'});
} else { } else {
@ -208,17 +209,19 @@ Rectangle {
Connections { Connections {
onSendSignalToWallet: { onSendSignalToWallet: {
if (msg.method === 'walletSetup_raiseKeyboard') { if (passphraseChange.visible) {
root.keyboardRaised = true; if (msg.method === 'walletSetup_raiseKeyboard') {
root.isPassword = msg.isPasswordField; root.keyboardRaised = true;
} else if (msg.method === 'walletSetup_lowerKeyboard') { root.isPassword = msg.isPasswordField;
root.keyboardRaised = false; } else if (msg.method === 'walletSetup_lowerKeyboard') {
} else if (msg.method === 'walletSecurity_changePassphraseCancelled') { root.keyboardRaised = false;
root.activeView = "security"; } else if (msg.method === 'walletSecurity_changePassphraseCancelled') {
} else if (msg.method === 'walletSecurity_changePassphraseSuccess') { root.activeView = "security";
root.activeView = "security"; } else if (msg.method === 'walletSecurity_changePassphraseSuccess') {
} else { root.activeView = "security";
sendToScript(msg); } else {
sendToScript(msg);
}
} }
} }
} }
@ -259,7 +262,7 @@ Rectangle {
color: hifi.colors.baseGray; color: hifi.colors.baseGray;
Component.onCompleted: { Component.onCompleted: {
commerce.getWalletStatus(); Commerce.getWalletStatus();
} }
} }
@ -280,7 +283,7 @@ Rectangle {
Connections { Connections {
target: GlobalServices target: GlobalServices
onMyUsernameChanged: { onMyUsernameChanged: {
commerce.getLoginStatus(); Commerce.getLoginStatus();
} }
} }
@ -294,7 +297,7 @@ Rectangle {
Connections { Connections {
onSendSignalToParent: { onSendSignalToParent: {
if (msg.method === "authSuccess") { if (msg.method === "authSuccess") {
commerce.getWalletStatus(); Commerce.getWalletStatus();
} else { } else {
sendToScript(msg); sendToScript(msg);
} }
@ -341,6 +344,7 @@ Rectangle {
passphraseChange.clearPassphraseFields(); passphraseChange.clearPassphraseFields();
passphraseChange.resetSubmitButton(); passphraseChange.resetSubmitButton();
} else if (msg.method === 'walletSecurity_changeSecurityImage') { } else if (msg.method === 'walletSecurity_changeSecurityImage') {
securityImageChange.initModel();
root.activeView = "securityImageChange"; root.activeView = "securityImageChange";
} }
} }

View file

@ -28,8 +28,8 @@ Item {
property bool historyReceived: false; property bool historyReceived: false;
property int pendingCount: 0; property int pendingCount: 0;
Hifi.QmlCommerce { Connections {
id: commerce; target: Commerce;
onBalanceResult : { onBalanceResult : {
balanceText.text = result.data.balance; balanceText.text = result.data.balance;
@ -135,8 +135,8 @@ Item {
onVisibleChanged: { onVisibleChanged: {
if (visible) { if (visible) {
historyReceived = false; historyReceived = false;
commerce.balance(); Commerce.balance();
commerce.history(); Commerce.history();
} else { } else {
refreshTimer.stop(); refreshTimer.stop();
} }
@ -165,8 +165,8 @@ Item {
interval: 4000; interval: 4000;
onTriggered: { onTriggered: {
console.log("Refreshing Wallet Home..."); console.log("Refreshing Wallet Home...");
commerce.balance(); Commerce.balance();
commerce.history(); Commerce.history();
} }
} }

View file

@ -40,8 +40,8 @@ Item {
source: "images/wallet-bg.jpg"; source: "images/wallet-bg.jpg";
} }
Hifi.QmlCommerce { Connections {
id: commerce; target: Commerce;
onSecurityImageResult: { onSecurityImageResult: {
if (!exists && root.lastPage === "step_2") { if (!exists && root.lastPage === "step_2") {
@ -235,6 +235,7 @@ Item {
height: 50; height: 50;
text: "Set Up Wallet"; text: "Set Up Wallet";
onClicked: { onClicked: {
securityImageSelection.initModel();
root.activeView = "step_2"; root.activeView = "step_2";
} }
} }
@ -250,7 +251,7 @@ Item {
height: 50; height: 50;
text: "Cancel"; text: "Cancel";
onClicked: { onClicked: {
sendSignalToWallet({method: 'walletSetup_cancelClicked'}); sendSignalToWallet({method: 'walletSetup_cancelClicked', referrer: root.referrer });
} }
} }
} }
@ -364,7 +365,7 @@ Item {
onClicked: { onClicked: {
root.lastPage = "step_2"; root.lastPage = "step_2";
var securityImagePath = securityImageSelection.getImagePathFromImageID(securityImageSelection.getSelectedImageIndex()) var securityImagePath = securityImageSelection.getImagePathFromImageID(securityImageSelection.getSelectedImageIndex())
commerce.chooseSecurityImage(securityImagePath); Commerce.chooseSecurityImage(securityImagePath);
root.activeView = "step_3"; root.activeView = "step_3";
passphraseSelection.clearPassphraseFields(); passphraseSelection.clearPassphraseFields();
} }
@ -447,7 +448,7 @@ Item {
onVisibleChanged: { onVisibleChanged: {
if (visible) { if (visible) {
commerce.getWalletAuthenticatedStatus(); Commerce.getWalletAuthenticatedStatus();
} }
} }
@ -533,7 +534,7 @@ Item {
onClicked: { onClicked: {
if (passphraseSelection.validateAndSubmitPassphrase()) { if (passphraseSelection.validateAndSubmitPassphrase()) {
root.lastPage = "step_3"; root.lastPage = "step_3";
commerce.generateKeyPair(); Commerce.generateKeyPair();
root.activeView = "step_4"; root.activeView = "step_4";
} }
} }
@ -666,7 +667,7 @@ Item {
onVisibleChanged: { onVisibleChanged: {
if (visible) { if (visible) {
commerce.getKeyFilePathIfExists(); Commerce.getKeyFilePathIfExists();
} }
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

View file

@ -123,11 +123,11 @@ Item {
hoverEnabled: true hoverEnabled: true
enabled: true enabled: true
onClicked: { onClicked: {
tabletInterface.playSound(TabletEnums.ButtonClick); Tablet.playSound(TabletEnums.ButtonClick);
newEntityButton.clicked(); newEntityButton.clicked();
} }
onEntered: { onEntered: {
tabletInterface.playSound(TabletEnums.ButtonHover); Tablet.playSound(TabletEnums.ButtonHover);
newEntityButton.state = "hover state"; newEntityButton.state = "hover state";
} }
onExited: { onExited: {

View file

@ -1,261 +0,0 @@
import QtQuick 2.5
import QtGraphicalEffects 1.0
import QtQuick.Layouts 1.3
import "../../styles-uit"
import "../audio" as HifiAudio
Item {
id: tablet
objectName: "tablet"
property int rowIndex: 6 // by default
property int columnIndex: 1 // point to 'go to location'
property int count: (flowMain.children.length - 1)
// used to look up a button by its uuid
function findButtonIndex(uuid) {
if (!uuid) {
return -1;
}
for (var i in flowMain.children) {
var child = flowMain.children[i];
if (child.uuid === uuid) {
return i;
}
}
return -1;
}
function sortButtons() {
var children = [];
for (var i = 0; i < flowMain.children.length; i++) {
children[i] = flowMain.children[i];
}
children.sort(function (a, b) {
if (a.sortOrder === b.sortOrder) {
// subsort by stableOrder, because JS sort is not stable in qml.
return a.stableOrder - b.stableOrder;
} else {
return a.sortOrder - b.sortOrder;
}
});
flowMain.children = children;
}
// called by C++ code when a button should be added to the tablet
function addButtonProxy(properties) {
var component = Qt.createComponent("TabletButton.qml");
var button = component.createObject(flowMain);
// copy all properites to button
var keys = Object.keys(properties).forEach(function (key) {
button[key] = properties[key];
});
// pass a reference to the tabletRoot object to the button.
if (tabletRoot) {
button.tabletRoot = tabletRoot;
} else {
button.tabletRoot = parent.parent;
}
sortButtons();
return button;
}
// called by C++ code when a button should be removed from the tablet
function removeButtonProxy(properties) {
var index = findButtonIndex(properties.uuid);
if (index < 0) {
console.log("Warning: Tablet.qml could not find button with uuid = " + properties.uuid);
} else {
flowMain.children[index].destroy();
}
}
Rectangle {
id: bgTopBar
height: 90
anchors {
top: parent.top
topMargin: 0
left: parent.left
leftMargin: 0
right: parent.right
rightMargin: 0
}
gradient: Gradient {
GradientStop {
position: 0
color: "#2b2b2b"
}
GradientStop {
position: 1
color: "#1e1e1e"
}
}
HifiAudio.MicBar {
anchors {
left: parent.left
leftMargin: 30
verticalCenter: parent.verticalCenter
}
}
Item {
width: 150
height: 50
anchors.right: parent.right
anchors.rightMargin: 30
anchors.verticalCenter: parent.verticalCenter
ColumnLayout {
anchors.fill: parent
RalewaySemiBold {
text: Account.loggedIn ? qsTr("Log out") : qsTr("Log in")
horizontalAlignment: Text.AlignRight
anchors.right: parent.right
font.pixelSize: 20
color: "#afafaf"
}
RalewaySemiBold {
visible: Account.loggedIn
height: Account.loggedIn ? parent.height/2 - parent.spacing/2 : 0
text: Account.loggedIn ? "[" + tabletRoot.usernameShort + "]" : ""
horizontalAlignment: Text.AlignRight
anchors.right: parent.right
font.pixelSize: 20
color: "#afafaf"
}
}
MouseArea {
anchors.fill: parent
onClicked: {
if (!Account.loggedIn) {
DialogsManager.showLoginDialog()
} else {
Account.logOut()
}
}
}
}
}
Rectangle {
id: bgMain
gradient: Gradient {
GradientStop {
position: 0
color: "#2b2b2b"
}
GradientStop {
position: 1
color: "#0f212e"
}
}
anchors.bottom: parent.bottom
anchors.bottomMargin: 0
anchors.right: parent.right
anchors.rightMargin: 0
anchors.left: parent.left
anchors.leftMargin: 0
anchors.top: bgTopBar.bottom
anchors.topMargin: 0
Flickable {
id: flickable
width: parent.width
height: parent.height
contentWidth: parent.width
contentHeight: flowMain.childrenRect.height + flowMain.anchors.topMargin + flowMain.anchors.bottomMargin + flowMain.spacing
clip: true
Flow {
id: flowMain
spacing: 16
anchors.right: parent.right
anchors.rightMargin: 30
anchors.left: parent.left
anchors.leftMargin: 30
anchors.bottom: parent.bottom
anchors.bottomMargin: 30
anchors.top: parent.top
anchors.topMargin: 30
}
}
}
function setCurrentItemState(state) {
var index = rowIndex + columnIndex;
if (index >= 0 && index <= count ) {
flowMain.children[index].state = state;
}
}
function nextItem() {
setCurrentItemState("base state");
var nextColumnIndex = (columnIndex + 3 + 1) % 3;
var nextIndex = rowIndex + nextColumnIndex;
if(nextIndex <= count) {
columnIndex = nextColumnIndex;
};
setCurrentItemState("hover state");
}
function previousItem() {
setCurrentItemState("base state");
var prevIndex = (columnIndex + 3 - 1) % 3;
if((rowIndex + prevIndex) <= count){
columnIndex = prevIndex;
}
setCurrentItemState("hover state");
}
function upItem() {
setCurrentItemState("base state");
rowIndex = rowIndex - 3;
if (rowIndex < 0 ) {
rowIndex = (count - (count % 3));
var index = rowIndex + columnIndex;
if(index > count) {
rowIndex = rowIndex - 3;
}
}
setCurrentItemState("hover state");
}
function downItem() {
setCurrentItemState("base state");
rowIndex = rowIndex + 3;
var index = rowIndex + columnIndex;
if (index > count ) {
rowIndex = 0;
}
setCurrentItemState("hover state");
}
function selectItem() {
flowMain.children[rowIndex + columnIndex].clicked();
if (tabletRoot) {
tabletRoot.playButtonClickSound();
}
}
Keys.onRightPressed: nextItem();
Keys.onLeftPressed: previousItem();
Keys.onDownPressed: downItem();
Keys.onUpPressed: upItem();
Keys.onReturnPressed: selectItem();
}

View file

@ -123,7 +123,6 @@ Item {
enabled: true enabled: true
preventStealing: true preventStealing: true
onClicked: { onClicked: {
console.log("Tablet Button Clicked!");
if (tabletButton.inDebugMode) { if (tabletButton.inDebugMode) {
if (tabletButton.isActive) { if (tabletButton.isActive) {
tabletButton.isActive = false; tabletButton.isActive = false;
@ -133,12 +132,12 @@ Item {
} }
tabletButton.clicked(); tabletButton.clicked();
if (tabletRoot) { if (tabletRoot) {
tabletInterface.playSound(TabletEnums.ButtonClick); Tablet.playSound(TabletEnums.ButtonClick);
} }
} }
onEntered: { onEntered: {
tabletButton.isEntered = true; tabletButton.isEntered = true;
tabletInterface.playSound(TabletEnums.ButtonHover); Tablet.playSound(TabletEnums.ButtonHover);
if (tabletButton.isActive) { if (tabletButton.isActive) {
tabletButton.state = "hover active state"; tabletButton.state = "hover active state";

View file

@ -0,0 +1,159 @@
import QtQuick 2.5
import QtGraphicalEffects 1.0
import QtQuick.Layouts 1.3
import "."
import "../../styles-uit"
import "../audio" as HifiAudio
Item {
id: tablet
objectName: "tablet"
property var tabletProxy: Tablet.getTablet("com.highfidelity.interface.tablet.system");
Rectangle {
id: bgTopBar
height: 90
anchors {
top: parent.top
left: parent.left
right: parent.right
}
gradient: Gradient {
GradientStop {
position: 0
color: "#2b2b2b"
}
GradientStop {
position: 1
color: "#1e1e1e"
}
}
HifiAudio.MicBar {
anchors {
left: parent.left
leftMargin: 30
verticalCenter: parent.verticalCenter
}
}
Item {
width: 150
height: 50
anchors.right: parent.right
anchors.rightMargin: 30
anchors.verticalCenter: parent.verticalCenter
ColumnLayout {
anchors.fill: parent
RalewaySemiBold {
text: Account.loggedIn ? qsTr("Log out") : qsTr("Log in")
horizontalAlignment: Text.AlignRight
anchors.right: parent.right
font.pixelSize: 20
color: "#afafaf"
}
RalewaySemiBold {
visible: Account.loggedIn
height: Account.loggedIn ? parent.height/2 - parent.spacing/2 : 0
text: Account.loggedIn ? "[" + tabletRoot.usernameShort + "]" : ""
horizontalAlignment: Text.AlignRight
anchors.right: parent.right
font.pixelSize: 20
color: "#afafaf"
}
}
MouseArea {
anchors.fill: parent
onClicked: {
if (!Account.loggedIn) {
DialogsManager.showLoginDialog()
} else {
Account.logOut()
}
}
}
}
}
Rectangle {
id: bgMain
clip: true
gradient: Gradient {
GradientStop {
position: 0
color: "#2b2b2b"
}
GradientStop {
position: 1
color: "#0f212e"
}
}
anchors.bottom: parent.bottom
anchors.right: parent.right
anchors.left: parent.left
anchors.top: bgTopBar.bottom
GridView {
id: flickable
anchors.top: parent.top
anchors.topMargin: 15
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
width: cellWidth * 3
cellHeight: 145
cellWidth: 145
model: tabletProxy.buttons
delegate: Item {
width: flickable.cellWidth
height: flickable.cellHeight
property var proxy: modelData
TabletButton {
id: tabletButton
anchors.centerIn: parent
onClicked: modelData.clicked()
state: wrapper.GridView.isCurrentItem ? "hover state" : "base state"
}
Connections {
target: modelData;
onPropertiesChanged: {
updateProperties();
}
}
Component.onCompleted: updateProperties()
function updateProperties() {
var keys = Object.keys(modelData.properties).forEach(function (key) {
if (tabletButton[key] !== modelData.properties[key]) {
tabletButton[key] = modelData.properties[key];
}
});
}
}
}
}
Keys.onRightPressed: flickable.moveCurrentIndexRight();
Keys.onLeftPressed: flickable.moveCurrentIndexLeft();
Keys.onDownPressed: flickable.moveCurrentIndexDown();
Keys.onUpPressed: flickable.moveCurrentIndexUp();
Keys.onReturnPressed: {
if (flickable.currentItem) {
flickable.currentItem.proxy.clicked();
if (tabletRoot) {
tabletRoot.playButtonClickSound();
}
}
}
}

View file

@ -75,12 +75,12 @@ FocusScope {
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
onEntered: { onEntered: {
tabletInterface.playSound(TabletEnums.ButtonHover); Tablet.playSound(TabletEnums.ButtonHover);
listView.currentIndex = index listView.currentIndex = index
} }
onClicked: { onClicked: {
tabletInterface.playSound(TabletEnums.ButtonClick); Tablet.playSound(TabletEnums.ButtonClick);
root.selected(item); root.selected(item);
} }
} }

View file

@ -67,37 +67,36 @@ Item {
function loadSource(url) { function loadSource(url) {
tabletApps.clear(); tabletApps.clear();
loader.source = ""; // make sure we load the qml fresh each time.
loader.source = url;
tabletApps.append({"appUrl": url, "isWebUrl": false, "scriptUrl": "", "appWebUrl": ""}); tabletApps.append({"appUrl": url, "isWebUrl": false, "scriptUrl": "", "appWebUrl": ""});
loader.load(url)
} }
function loadQMLOnTop(url) { function loadQMLOnTop(url) {
tabletApps.append({"appUrl": url, "isWebUrl": false, "scriptUrl": "", "appWebUrl": ""}); tabletApps.append({"appUrl": url, "isWebUrl": false, "scriptUrl": "", "appWebUrl": ""});
loader.source = ""; loader.load(tabletApps.get(currentApp).appUrl, function(){
loader.source = tabletApps.get(currentApp).appUrl; if (loader.item.hasOwnProperty("gotoPreviousApp")) {
if (loader.item.hasOwnProperty("gotoPreviousApp")) { loader.item.gotoPreviousApp = true;
loader.item.gotoPreviousApp = true; }
} })
} }
function loadWebOnTop(url, injectJavaScriptUrl) { function loadWebContent(source, url, injectJavaScriptUrl) {
tabletApps.append({"appUrl": loader.source, "isWebUrl": true, "scriptUrl": injectJavaScriptUrl, "appWebUrl": url}); tabletApps.append({"appUrl": source, "isWebUrl": true, "scriptUrl": injectJavaScriptUrl, "appWebUrl": url});
loader.item.url = tabletApps.get(currentApp).appWebUrl; loader.load(source, function() {
loader.item.scriptUrl = tabletApps.get(currentApp).scriptUrl; loader.item.scriptURL = injectJavaScriptUrl;
if (loader.item.hasOwnProperty("gotoPreviousApp")) { loader.item.url = url;
loader.item.gotoPreviousApp = true; if (loader.item.hasOwnProperty("gotoPreviousApp")) {
} loader.item.gotoPreviousApp = true;
}
});
} }
function loadWebBase() { function loadWebBase(url, injectJavaScriptUrl) {
loader.source = ""; loadWebContent("hifi/tablet/TabletWebView.qml", url, injectJavaScriptUrl);
loader.source = "TabletWebView.qml";
} }
function loadTabletWebBase() { function loadTabletWebBase(url, injectJavaScriptUrl) {
loader.source = ""; loadWebContent("hifi/tablet/BlocksWebView.qml", url, injectJavaScriptUrl);
loader.source = "./BlocksWebView.qml";
} }
function returnToPreviousApp() { function returnToPreviousApp() {
@ -109,7 +108,7 @@ Item {
loadSource("TabletWebView.qml"); loadSource("TabletWebView.qml");
loadWebUrl(webUrl, scriptUrl); loadWebUrl(webUrl, scriptUrl);
} else { } else {
loader.source = tabletApps.get(currentApp).appUrl; loader.load(tabletApps.get(currentApp).appUrl);
} }
} }
@ -172,47 +171,79 @@ Item {
} }
} }
Loader { // Hook up callback for clara.io download from the marketplace.
id: loader Connections {
objectName: "loader" id: eventBridgeConnection
asynchronous: false target: eventBridge
onWebEventReceived: {
width: parent.width if (message.slice(0, 17) === "CLARA.IO DOWNLOAD") {
height: parent.height ApplicationInterface.addAssetToWorldFromURL(message.slice(18));
// Hook up callback for clara.io download from the marketplace.
Connections {
id: eventBridgeConnection
target: eventBridge
onWebEventReceived: {
if (message.slice(0, 17) === "CLARA.IO DOWNLOAD") {
ApplicationInterface.addAssetToWorldFromURL(message.slice(18));
}
}
}
onLoaded: {
if (loader.item.hasOwnProperty("sendToScript")) {
loader.item.sendToScript.connect(tabletRoot.sendToScript);
}
if (loader.item.hasOwnProperty("setRootMenu")) {
loader.item.setRootMenu(tabletRoot.rootMenu, tabletRoot.subMenu);
}
loader.item.forceActiveFocus();
if (openModal) {
openModal.canceled();
openModal.destroy();
openModal = null;
}
if (openBrowser) {
openBrowser.destroy();
openBrowser = null;
} }
} }
} }
Item {
id: loader
objectName: "loader";
anchors.fill: parent;
property string source: "";
property var item: null;
signal loaded;
onWidthChanged: {
if (loader.item) {
loader.item.width = loader.width;
}
}
onHeightChanged: {
if (loader.item) {
loader.item.height = loader.height;
}
}
function load(newSource, callback) {
if (loader.source == newSource) {
loader.loaded();
return;
}
if (loader.item) {
loader.item.destroy();
loader.item = null;
}
QmlSurface.load(newSource, loader, function(newItem) {
loader.item = newItem;
loader.item.width = loader.width;
loader.item.height = loader.height;
loader.loaded();
if (loader.item.hasOwnProperty("sendToScript")) {
loader.item.sendToScript.connect(tabletRoot.sendToScript);
}
if (loader.item.hasOwnProperty("setRootMenu")) {
loader.item.setRootMenu(tabletRoot.rootMenu, tabletRoot.subMenu);
}
loader.item.forceActiveFocus();
if (openModal) {
openModal.canceled();
openModal.destroy();
openModal = null;
}
if (openBrowser) {
openBrowser.destroy();
openBrowser = null;
}
if (callback) {
callback();
}
});
}
}
width: 480 width: 480
height: 706 height: 706

View file

@ -59,26 +59,25 @@ Windows.ScrollingWindow {
} }
function loadSource(url) { function loadSource(url) {
loader.source = ""; // make sure we load the qml fresh each time. loader.load(url)
loader.source = url;
} }
function loadWebBase() { function loadWebContent(source, url, injectJavaScriptUrl) {
loader.source = ""; loader.load(source, function() {
loader.source = "WindowWebView.qml"; loader.item.scriptURL = injectJavaScriptUrl;
loader.item.url = url;
if (loader.item.hasOwnProperty("closeButtonVisible")) {
loader.item.closeButtonVisible = false;
}
});
} }
function loadTabletWebBase() { function loadWebBase(url, injectJavaScriptUrl) {
loader.source = ""; loadWebContent("hifi/tablet/TabletWebView.qml", url, injectJavaScriptUrl);
loader.source = "./BlocksWebView.qml";
} }
function loadWebUrl(url, injectedJavaScriptUrl) { function loadTabletWebBase(url, injectJavaScriptUrl) {
loader.item.url = url; loadWebContent("hifi/tablet/BlocksWebView.qml", url, injectJavaScriptUrl);
loader.item.scriptURL = injectedJavaScriptUrl;
if (loader.item.hasOwnProperty("closeButtonVisible")) {
loader.item.closeButtonVisible = false;
}
} }
// used to send a message from qml to interface script. // used to send a message from qml to interface script.
@ -111,38 +110,68 @@ Windows.ScrollingWindow {
username = newUsername; username = newUsername;
} }
Loader { // Hook up callback for clara.io download from the marketplace.
Connections {
id: eventBridgeConnection
target: eventBridge
onWebEventReceived: {
if (message.slice(0, 17) === "CLARA.IO DOWNLOAD") {
ApplicationInterface.addAssetToWorldFromURL(message.slice(18));
}
}
}
Item {
id: loader id: loader
objectName: "loader" objectName: "loader";
asynchronous: false property string source: "";
property var item: null;
height: pane.scrollHeight height: pane.scrollHeight
width: pane.contentWidth width: pane.contentWidth
anchors.left: parent.left anchors.left: parent.left
anchors.top: parent.top anchors.top: parent.top
signal loaded;
// Hook up callback for clara.io download from the marketplace.
Connections { onWidthChanged: {
id: eventBridgeConnection if (loader.item) {
target: eventBridge loader.item.width = loader.width;
onWebEventReceived: {
if (message.slice(0, 17) === "CLARA.IO DOWNLOAD") {
ApplicationInterface.addAssetToWorldFromURL(message.slice(18));
}
} }
} }
onLoaded: { onHeightChanged: {
if (loader.item.hasOwnProperty("sendToScript")) { if (loader.item) {
loader.item.sendToScript.connect(tabletRoot.sendToScript); loader.item.height = loader.height;
} }
if (loader.item.hasOwnProperty("setRootMenu")) { }
loader.item.setRootMenu(tabletRoot.rootMenu, tabletRoot.subMenu);
function load(newSource, callback) {
if (loader.item) {
loader.item.destroy();
loader.item = null;
} }
loader.item.forceActiveFocus();
QmlSurface.load(newSource, loader, function(newItem) {
loader.item = newItem;
loader.item.width = loader.width;
loader.item.height = loader.height;
loader.loaded();
if (loader.item.hasOwnProperty("sendToScript")) {
loader.item.sendToScript.connect(tabletRoot.sendToScript);
}
if (loader.item.hasOwnProperty("setRootMenu")) {
loader.item.setRootMenu(tabletRoot.rootMenu, tabletRoot.subMenu);
}
loader.item.forceActiveFocus();
if (callback) {
callback();
}
});
} }
} }
implicitWidth: 480 implicitWidth: 480
implicitHeight: 706 implicitHeight: 706
} }

View file

@ -10,6 +10,8 @@ Window {
horizontalSpacers: horizontal horizontalSpacers: horizontal
verticalSpacers: !horizontal verticalSpacers: !horizontal
} }
property var tabletProxy;
property var buttonModel: ListModel {}
hideBackground: true hideBackground: true
resizable: false resizable: false
destroyOnCloseButton: false destroyOnCloseButton: false
@ -22,24 +24,32 @@ Window {
activator: Item {} activator: Item {}
property bool horizontal: true property bool horizontal: true
property real buttonSize: 50; property real buttonSize: 50;
property var buttons: []
property var container: horizontal ? row : column
Settings { Settings {
category: "toolbar/" + window.objectName category: "toolbar/" + window.objectName
property alias x: window.x property alias x: window.x
property alias y: window.y property alias y: window.y
} }
Component {
id: buttonComponent
ToolbarButton {
id: toolbarButton
property var proxy: modelData;
onClicked: proxy.clicked()
Component.onCompleted: updateProperties()
onHorizontalChanged: { Connections {
var newParent = horizontal ? row : column; target: proxy;
for (var i in buttons) { onPropertiesChanged: updateProperties();
var child = buttons[i]; }
child.parent = newParent;
if (horizontal) { function updateProperties() {
child.y = 0 Object.keys(proxy.properties).forEach(function (key) {
} else { if (toolbarButton[key] !== proxy.properties[key]) {
child.x = 0 toolbarButton[key] = proxy.properties[key];
}
});
} }
} }
} }
@ -51,97 +61,22 @@ Window {
Row { Row {
id: row id: row
visible: window.horizontal
spacing: 6 spacing: 6
Repeater {
model: buttonModel
delegate: buttonComponent
}
} }
Column { Column {
id: column id: column
visible: !window.horizontal
spacing: 6 spacing: 6
} Repeater {
model: buttonModel
Component { id: toolbarButtonBuilder; ToolbarButton { } } delegate: buttonComponent
}
function findButtonIndex(name) {
if (!name) {
return -1;
}
for (var i in buttons) {
var child = buttons[i];
if (child.objectName === name) {
return i;
} }
} }
return -1;
}
function findButton(name) {
var index = findButtonIndex(name);
if (index < 0) {
return;
}
return buttons[index];
}
function sortButtons() {
var children = [];
for (var i = 0; i < container.children.length; i++) {
children[i] = container.children[i];
}
children.sort(function (a, b) {
if (a.sortOrder === b.sortOrder) {
// subsort by stableOrder, because JS sort is not stable in qml.
return a.stableOrder - b.stableOrder;
} else {
return a.sortOrder - b.sortOrder;
}
});
container.children = children;
}
function addButton(properties) {
properties = properties || {}
// If a name is specified, then check if there's an existing button with that name
// and return it if so. This will allow multiple clients to listen to a single button,
// and allow scripts to be idempotent so they don't duplicate buttons if they're reloaded
var result = findButton(properties.objectName);
if (result) {
for (var property in properties) {
result[property] = properties[property];
}
return result;
}
properties.toolbar = this;
properties.opacity = 0;
result = toolbarButtonBuilder.createObject(container, properties);
buttons.push(result);
result.opacity = 1;
sortButtons();
fadeIn(null);
return result;
}
function removeButton(name) {
var index = findButtonIndex(name);
if (index < -1) {
console.warn("Tried to remove non-existent button " + name);
return;
}
buttons[index].destroy();
buttons.splice(index, 1);
if (buttons.length === 0) {
fadeOut(null);
}
} }
} }

View file

@ -26,7 +26,8 @@ StateImage {
property string activeHoverIcon: button.activeIcon property string activeHoverIcon: button.activeIcon
property int sortOrder: 100 property int sortOrder: 100
property int stableSortOrder: 0 property int stableOrder: 0
property var uuid;
signal clicked() signal clicked()

Binary file not shown.

View file

@ -1496,6 +1496,14 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
} }
}); });
connect(getEntities()->getTree().get(), &EntityTree::deletingEntity, [=](const EntityItemID& entityItemID) {
auto avatarManager = DependencyManager::get<AvatarManager>();
auto myAvatar = avatarManager ? avatarManager->getMyAvatar() : nullptr;
if (myAvatar) {
myAvatar->clearAvatarEntity(entityItemID);
}
});
// Keyboard focus handling for Web overlays. // Keyboard focus handling for Web overlays.
auto overlays = &(qApp->getOverlays()); auto overlays = &(qApp->getOverlays());
connect(overlays, &Overlays::overlayDeleted, [=](const OverlayID& overlayID) { connect(overlays, &Overlays::overlayDeleted, [=](const OverlayID& overlayID) {
@ -2240,27 +2248,65 @@ extern void setupPreferences();
void Application::initializeUi() { void Application::initializeUi() {
// Make sure all QML surfaces share the main thread GL context // Make sure all QML surfaces share the main thread GL context
OffscreenQmlSurface::setSharedContext(_offscreenContext->getContext()); OffscreenQmlSurface::setSharedContext(_offscreenContext->getContext());
OffscreenQmlSurface::addWhitelistContextHandler(QUrl{ "OverlayWindowTest.qml" },
[](QQmlContext* context) {
qDebug() << "Whitelist OverlayWindow worked";
context->setContextProperty("OverlayWindowTestString", "TestWorked");
});
OffscreenQmlSurface::addWhitelistContextHandler(QUrl{ "hifi/audio/Audio.qml" },
[](QQmlContext* context) {
qDebug() << "QQQ" << __FUNCTION__ << "Whitelist Audio worked";
});
AddressBarDialog::registerType(); AddressBarDialog::registerType();
ErrorDialog::registerType(); ErrorDialog::registerType();
LoginDialog::registerType(); LoginDialog::registerType();
Tooltip::registerType(); Tooltip::registerType();
UpdateDialog::registerType(); UpdateDialog::registerType();
QmlCommerce::registerType(); QmlContextCallback callback = [](QQmlContext* context) {
context->setContextProperty("Commerce", new QmlCommerce());
};
OffscreenQmlSurface::addWhitelistContextHandler({
QUrl{ "hifi/commerce/checkout/Checkout.qml" },
QUrl{ "hifi/commerce/common/CommerceLightbox.qml" },
QUrl{ "hifi/commerce/common/EmulatedMarketplaceHeader.qml" },
QUrl{ "hifi/commerce/common/FirstUseTutorial.qml" },
QUrl{ "hifi/commerce/common/SortableListModel.qml" },
QUrl{ "hifi/commerce/inspectionCertificate/InspectionCertificate.qml" },
QUrl{ "hifi/commerce/purchases/PurchasedItem.qml" },
QUrl{ "hifi/commerce/purchases/Purchases.qml" },
QUrl{ "hifi/commerce/wallet/Help.qml" },
QUrl{ "hifi/commerce/wallet/NeedsLogIn.qml" },
QUrl{ "hifi/commerce/wallet/PassphraseChange.qml" },
QUrl{ "hifi/commerce/wallet/PassphraseModal.qml" },
QUrl{ "hifi/commerce/wallet/PassphraseSelection.qml" },
QUrl{ "hifi/commerce/wallet/Security.qml" },
QUrl{ "hifi/commerce/wallet/SecurityImageChange.qml" },
QUrl{ "hifi/commerce/wallet/SecurityImageModel.qml" },
QUrl{ "hifi/commerce/wallet/SecurityImageSelection.qml" },
QUrl{ "hifi/commerce/wallet/SendMoney.qml" },
QUrl{ "hifi/commerce/wallet/Wallet.qml" },
QUrl{ "hifi/commerce/wallet/WalletHome.qml" },
QUrl{ "hifi/commerce/wallet/WalletSetup.qml" },
}, callback);
qmlRegisterType<ResourceImageItem>("Hifi", 1, 0, "ResourceImageItem"); qmlRegisterType<ResourceImageItem>("Hifi", 1, 0, "ResourceImageItem");
qmlRegisterType<Preference>("Hifi", 1, 0, "Preference"); qmlRegisterType<Preference>("Hifi", 1, 0, "Preference");
qmlRegisterType<WebBrowserSuggestionsEngine>("HifiWeb", 1, 0, "WebBrowserSuggestionsEngine"); qmlRegisterType<WebBrowserSuggestionsEngine>("HifiWeb", 1, 0, "WebBrowserSuggestionsEngine");
{
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
tabletScriptingInterface->getTablet(SYSTEM_TABLET);
}
auto offscreenUi = DependencyManager::get<OffscreenUi>(); auto offscreenUi = DependencyManager::get<OffscreenUi>();
offscreenUi->create(); offscreenUi->create();
auto surfaceContext = offscreenUi->getSurfaceContext(); auto surfaceContext = offscreenUi->getSurfaceContext();
offscreenUi->setProxyWindow(_window->windowHandle()); offscreenUi->setProxyWindow(_window->windowHandle());
offscreenUi->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/"));
// OffscreenUi is a subclass of OffscreenQmlSurface specifically designed to // OffscreenUi is a subclass of OffscreenQmlSurface specifically designed to
// support the window management and scripting proxies for VR use // support the window management and scripting proxies for VR use
offscreenUi->createDesktop(QString("qrc:///qml/hifi/Desktop.qml")); offscreenUi->createDesktop(QString("hifi/Desktop.qml"));
// FIXME either expose so that dialogs can set this themselves or // FIXME either expose so that dialogs can set this themselves or
// do better detection in the offscreen UI of what has focus // do better detection in the offscreen UI of what has focus
@ -2328,9 +2374,6 @@ void Application::initializeUi() {
surfaceContext->setContextProperty("InputConfiguration", DependencyManager::get<InputConfiguration>().data()); surfaceContext->setContextProperty("InputConfiguration", DependencyManager::get<InputConfiguration>().data());
surfaceContext->setContextProperty("Account", AccountScriptingInterface::getInstance()); surfaceContext->setContextProperty("Account", AccountScriptingInterface::getInstance());
surfaceContext->setContextProperty("Tablet", DependencyManager::get<TabletScriptingInterface>().data());
// Tablet inteference with Tablet.qml. Need to avoid this in QML space
surfaceContext->setContextProperty("tabletInterface", DependencyManager::get<TabletScriptingInterface>().data());
surfaceContext->setContextProperty("DialogsManager", _dialogsManagerScriptingInterface); surfaceContext->setContextProperty("DialogsManager", _dialogsManagerScriptingInterface);
surfaceContext->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance()); surfaceContext->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance());
surfaceContext->setContextProperty("FaceTracker", DependencyManager::get<DdeFaceTracker>().data()); surfaceContext->setContextProperty("FaceTracker", DependencyManager::get<DdeFaceTracker>().data());
@ -4280,9 +4323,11 @@ void Application::updateLOD(float deltaTime) const {
PerformanceTimer perfTimer("LOD"); PerformanceTimer perfTimer("LOD");
// adjust it unless we were asked to disable this feature, or if we're currently in throttleRendering mode // adjust it unless we were asked to disable this feature, or if we're currently in throttleRendering mode
if (!isThrottleRendering()) { if (!isThrottleRendering()) {
float batchTime = (float)_gpuContext->getFrameTimerBatchAverage(); float presentTime = getActiveDisplayPlugin()->getAveragePresentTime();
float engineRunTime = (float)(_renderEngine->getConfiguration().get()->getCPURunTime()); float engineRunTime = (float)(_renderEngine->getConfiguration().get()->getCPURunTime());
DependencyManager::get<LODManager>()->autoAdjustLOD(batchTime, engineRunTime, deltaTime); float gpuTime = getGPUContext()->getFrameTimerGPUAverage();
float maxRenderTime = glm::max(gpuTime, glm::max(presentTime, engineRunTime));
DependencyManager::get<LODManager>()->autoAdjustLOD(maxRenderTime, deltaTime);
} else { } else {
DependencyManager::get<LODManager>()->resetLODAdjust(); DependencyManager::get<LODManager>()->resetLODAdjust();
} }
@ -5828,9 +5873,9 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe
qScriptRegisterMetaType(scriptEngine.data(), wrapperToScriptValue<TabletProxy>, wrapperFromScriptValue<TabletProxy>); qScriptRegisterMetaType(scriptEngine.data(), wrapperToScriptValue<TabletProxy>, wrapperFromScriptValue<TabletProxy>);
qScriptRegisterMetaType(scriptEngine.data(), qScriptRegisterMetaType(scriptEngine.data(),
wrapperToScriptValue<TabletButtonProxy>, wrapperFromScriptValue<TabletButtonProxy>); wrapperToScriptValue<TabletButtonProxy>, wrapperFromScriptValue<TabletButtonProxy>);
// Tablet inteference with Tablet.qml. Need to avoid this in QML space
scriptEngine->registerGlobalObject("tabletInterface", DependencyManager::get<TabletScriptingInterface>().data());
scriptEngine->registerGlobalObject("Tablet", DependencyManager::get<TabletScriptingInterface>().data()); scriptEngine->registerGlobalObject("Tablet", DependencyManager::get<TabletScriptingInterface>().data());
// FIXME remove these deprecated names for the tablet scripting interface
scriptEngine->registerGlobalObject("tabletInterface", DependencyManager::get<TabletScriptingInterface>().data());
auto toolbarScriptingInterface = DependencyManager::get<ToolbarScriptingInterface>().data(); auto toolbarScriptingInterface = DependencyManager::get<ToolbarScriptingInterface>().data();
DependencyManager::get<TabletScriptingInterface>().data()->setToolbarScriptingInterface(toolbarScriptingInterface); DependencyManager::get<TabletScriptingInterface>().data()->setToolbarScriptingInterface(toolbarScriptingInterface);
@ -7237,13 +7282,17 @@ void Application::updateDisplayMode() {
} }
auto offscreenUi = DependencyManager::get<OffscreenUi>(); auto offscreenUi = DependencyManager::get<OffscreenUi>();
auto desktop = offscreenUi->getDesktop();
// Make the switch atomic from the perspective of other threads // Make the switch atomic from the perspective of other threads
{ {
std::unique_lock<std::mutex> lock(_displayPluginLock); std::unique_lock<std::mutex> lock(_displayPluginLock);
// Tell the desktop to no reposition (which requires plugin info), until we have set the new plugin, below. bool wasRepositionLocked = false;
bool wasRepositionLocked = offscreenUi->getDesktop()->property("repositionLocked").toBool(); if (desktop) {
offscreenUi->getDesktop()->setProperty("repositionLocked", true); // Tell the desktop to no reposition (which requires plugin info), until we have set the new plugin, below.
wasRepositionLocked = offscreenUi->getDesktop()->property("repositionLocked").toBool();
offscreenUi->getDesktop()->setProperty("repositionLocked", true);
}
if (_displayPlugin) { if (_displayPlugin) {
disconnect(_displayPlugin.get(), &DisplayPlugin::presented, this, &Application::onPresent); disconnect(_displayPlugin.get(), &DisplayPlugin::presented, this, &Application::onPresent);
@ -7289,7 +7338,6 @@ void Application::updateDisplayMode() {
getApplicationCompositor().setDisplayPlugin(newDisplayPlugin); getApplicationCompositor().setDisplayPlugin(newDisplayPlugin);
_displayPlugin = newDisplayPlugin; _displayPlugin = newDisplayPlugin;
connect(_displayPlugin.get(), &DisplayPlugin::presented, this, &Application::onPresent, Qt::DirectConnection); connect(_displayPlugin.get(), &DisplayPlugin::presented, this, &Application::onPresent, Qt::DirectConnection);
auto desktop = offscreenUi->getDesktop();
if (desktop) { if (desktop) {
desktop->setProperty("repositionLocked", wasRepositionLocked); desktop->setProperty("repositionLocked", wasRepositionLocked);
} }

View file

@ -19,6 +19,7 @@
#include "LODManager.h" #include "LODManager.h"
Setting::Handle<float> desktopLODDecreaseFPS("desktopLODDecreaseFPS", DEFAULT_DESKTOP_LOD_DOWN_FPS); Setting::Handle<float> desktopLODDecreaseFPS("desktopLODDecreaseFPS", DEFAULT_DESKTOP_LOD_DOWN_FPS);
Setting::Handle<float> hmdLODDecreaseFPS("hmdLODDecreaseFPS", DEFAULT_HMD_LOD_DOWN_FPS); Setting::Handle<float> hmdLODDecreaseFPS("hmdLODDecreaseFPS", DEFAULT_HMD_LOD_DOWN_FPS);
@ -39,156 +40,95 @@ float LODManager::getLODIncreaseFPS() {
return getDesktopLODIncreaseFPS(); return getDesktopLODIncreaseFPS();
} }
void LODManager::autoAdjustLOD(float batchTime, float engineRunTime, float deltaTimeSec) { // We use a "time-weighted running average" of the renderTime and compare it against min/max thresholds
// to determine if we should adjust the level of detail (LOD).
//
// A time-weighted running average has a timescale which determines how fast the average tracks the measured
// value in real-time. Given a step-function in the mesured value, and assuming measurements happen
// faster than the runningAverage is computed, the error between the value and its runningAverage will be
// reduced by 1/e every timescale of real-time that passes.
const float LOD_ADJUST_RUNNING_AVG_TIMESCALE = 0.1f; // sec
//
// Assuming the measured value is affected by logic invoked by the runningAverage bumping up against its
// thresholds, we expect the adjustment to introduce a step-function. We want the runningAverage settle
// to the new value BEFORE we test it aginst its thresholds again. Hence we test on a period that is a few
// multiples of the running average timescale:
const uint64_t LOD_AUTO_ADJUST_PERIOD = 5 * (uint64_t)(LOD_ADJUST_RUNNING_AVG_TIMESCALE * (float)USECS_PER_MSEC); // usec
// NOTE: our first ~100 samples at app startup are completely all over the place, and we don't const float LOD_AUTO_ADJUST_DECREMENT_FACTOR = 0.8f;
// really want to count them in our average, so we will ignore the real frame rates and stuff const float LOD_AUTO_ADJUST_INCREMENT_FACTOR = 1.2f;
// our moving average with simulated good data
const int IGNORE_THESE_SAMPLES = 100;
if (_fpsAverageUpWindow.getSampleCount() < IGNORE_THESE_SAMPLES) {
_lastStable = _lastUpShift = _lastDownShift = usecTimestampNow();
}
void LODManager::autoAdjustLOD(float renderTime, float realTimeDelta) {
// compute time-weighted running average renderTime // compute time-weighted running average renderTime
const float OVERLAY_AND_SWAP_TIME_BUDGET = 2.0f; // msec // Note: we MUST clamp the blend to 1.0 for stability
float renderTime = batchTime + OVERLAY_AND_SWAP_TIME_BUDGET; float blend = (realTimeDelta < LOD_ADJUST_RUNNING_AVG_TIMESCALE) ? realTimeDelta / LOD_ADJUST_RUNNING_AVG_TIMESCALE : 1.0f;
float maxTime = glm::max(renderTime, engineRunTime); _avgRenderTime = (1.0f - blend) * _avgRenderTime + blend * renderTime; // msec
const float BLEND_TIMESCALE = 0.3f; // sec if (!_automaticLODAdjust) {
const float MIN_DELTA_TIME = 0.001f; // early exit
const float safeDeltaTime = glm::max(deltaTimeSec, MIN_DELTA_TIME); return;
float blend = BLEND_TIMESCALE / safeDeltaTime;
if (blend > 1.0f) {
blend = 1.0f;
} }
_avgRenderTime = (1.0f - blend) * _avgRenderTime + blend * maxTime; // msec
// translate into fps for legacy implementation float oldOctreeSizeScale = _octreeSizeScale;
float currentFPS = (float)MSECS_PER_SECOND / _avgRenderTime; float currentFPS = (float)MSECS_PER_SECOND / _avgRenderTime;
uint64_t now = usecTimestampNow();
_fpsAverageStartWindow.updateAverage(currentFPS); if (currentFPS < getLODDecreaseFPS()) {
_fpsAverageDownWindow.updateAverage(currentFPS); if (now > _decreaseFPSExpiry) {
_fpsAverageUpWindow.updateAverage(currentFPS); _decreaseFPSExpiry = now + LOD_AUTO_ADJUST_PERIOD;
quint64 now = usecTimestampNow();
quint64 elapsedSinceDownShift = now - _lastDownShift;
quint64 elapsedSinceUpShift = now - _lastUpShift;
quint64 lastStableOrUpshift = glm::max(_lastUpShift, _lastStable);
quint64 elapsedSinceStableOrUpShift = now - lastStableOrUpshift;
if (_automaticLODAdjust) {
bool changed = false;
// LOD Downward adjustment
// If we've been downshifting, we watch a shorter downshift window so that we will quickly move toward our
// target frame rate. But if we haven't just done a downshift (either because our last shift was an upshift,
// or because we've just started out) then we look at a much longer window to consider whether or not to start
// downshifting.
bool doDownShift = false;
if (_isDownshifting) {
// only consider things if our DOWN_SHIFT time has elapsed...
if (elapsedSinceDownShift > DOWN_SHIFT_ELPASED) {
doDownShift = _fpsAverageDownWindow.getAverage() < getLODDecreaseFPS();
if (!doDownShift) {
qCDebug(interfaceapp) << "---- WE APPEAR TO BE DONE DOWN SHIFTING -----";
_isDownshifting = false;
_lastStable = now;
}
}
} else {
doDownShift = (elapsedSinceStableOrUpShift > START_SHIFT_ELPASED
&& _fpsAverageStartWindow.getAverage() < getLODDecreaseFPS());
}
if (doDownShift) {
// Octree items... stepwise adjustment
if (_octreeSizeScale > ADJUST_LOD_MIN_SIZE_SCALE) { if (_octreeSizeScale > ADJUST_LOD_MIN_SIZE_SCALE) {
_octreeSizeScale *= ADJUST_LOD_DOWN_BY; _octreeSizeScale *= LOD_AUTO_ADJUST_DECREMENT_FACTOR;
if (_octreeSizeScale < ADJUST_LOD_MIN_SIZE_SCALE) { if (_octreeSizeScale < ADJUST_LOD_MIN_SIZE_SCALE) {
_octreeSizeScale = ADJUST_LOD_MIN_SIZE_SCALE; _octreeSizeScale = ADJUST_LOD_MIN_SIZE_SCALE;
} }
changed = true; qCDebug(interfaceapp) << "adjusting LOD DOWN"
} << "fps =" << currentFPS
<< "targetFPS =" << getLODDecreaseFPS()
if (changed) { << "octreeSizeScale =" << _octreeSizeScale;
if (_isDownshifting) {
// subsequent downshift
qCDebug(interfaceapp) << "adjusting LOD DOWN..."
<< "average fps for last "<< DOWN_SHIFT_WINDOW_IN_SECS <<"seconds was "
<< _fpsAverageDownWindow.getAverage()
<< "minimum is:" << getLODDecreaseFPS()
<< "elapsedSinceDownShift:" << elapsedSinceDownShift
<< " NEW _octreeSizeScale=" << _octreeSizeScale;
} else {
// first downshift
qCDebug(interfaceapp) << "adjusting LOD DOWN after initial delay..."
<< "average fps for last "<< START_DELAY_WINDOW_IN_SECS <<"seconds was "
<< _fpsAverageStartWindow.getAverage()
<< "minimum is:" << getLODDecreaseFPS()
<< "elapsedSinceUpShift:" << elapsedSinceUpShift
<< " NEW _octreeSizeScale=" << _octreeSizeScale;
}
_lastDownShift = now;
_isDownshifting = true;
emit LODDecreased(); emit LODDecreased();
} }
} else { _decreaseFPSExpiry = now + LOD_AUTO_ADJUST_PERIOD;
// LOD Upward adjustment
if (elapsedSinceUpShift > UP_SHIFT_ELPASED) {
if (_fpsAverageUpWindow.getAverage() > getLODIncreaseFPS()) {
// Octee items... stepwise adjustment
if (_octreeSizeScale < ADJUST_LOD_MAX_SIZE_SCALE) {
if (_octreeSizeScale < ADJUST_LOD_MIN_SIZE_SCALE) {
_octreeSizeScale = ADJUST_LOD_MIN_SIZE_SCALE;
} else {
_octreeSizeScale *= ADJUST_LOD_UP_BY;
}
if (_octreeSizeScale > ADJUST_LOD_MAX_SIZE_SCALE) {
_octreeSizeScale = ADJUST_LOD_MAX_SIZE_SCALE;
}
changed = true;
}
}
if (changed) {
qCDebug(interfaceapp) << "adjusting LOD UP... average fps for last "<< UP_SHIFT_WINDOW_IN_SECS <<"seconds was "
<< _fpsAverageUpWindow.getAverage()
<< "upshift point is:" << getLODIncreaseFPS()
<< "elapsedSinceUpShift:" << elapsedSinceUpShift
<< " NEW _octreeSizeScale=" << _octreeSizeScale;
_lastUpShift = now;
_isDownshifting = false;
emit LODIncreased();
}
}
} }
_increaseFPSExpiry = now + LOD_AUTO_ADJUST_PERIOD;
if (changed) { } else if (currentFPS > getLODIncreaseFPS()) {
auto lodToolsDialog = DependencyManager::get<DialogsManager>()->getLodToolsDialog(); if (now > _increaseFPSExpiry) {
if (lodToolsDialog) { _increaseFPSExpiry = now + LOD_AUTO_ADJUST_PERIOD;
lodToolsDialog->reloadSliders(); if (_octreeSizeScale < ADJUST_LOD_MAX_SIZE_SCALE) {
if (_octreeSizeScale < ADJUST_LOD_MIN_SIZE_SCALE) {
_octreeSizeScale = ADJUST_LOD_MIN_SIZE_SCALE;
} else {
_octreeSizeScale *= LOD_AUTO_ADJUST_INCREMENT_FACTOR;
}
if (_octreeSizeScale > ADJUST_LOD_MAX_SIZE_SCALE) {
_octreeSizeScale = ADJUST_LOD_MAX_SIZE_SCALE;
}
qCDebug(interfaceapp) << "adjusting LOD UP"
<< "fps =" << currentFPS
<< "targetFPS =" << getLODDecreaseFPS()
<< "octreeSizeScale =" << _octreeSizeScale;
emit LODIncreased();
} }
_increaseFPSExpiry = now + LOD_AUTO_ADJUST_PERIOD;
} }
_decreaseFPSExpiry = now + LOD_AUTO_ADJUST_PERIOD;
} else {
_increaseFPSExpiry = now + LOD_AUTO_ADJUST_PERIOD;
_decreaseFPSExpiry = _increaseFPSExpiry;
}
if (oldOctreeSizeScale != _octreeSizeScale) {
auto lodToolsDialog = DependencyManager::get<DialogsManager>()->getLodToolsDialog();
if (lodToolsDialog) {
lodToolsDialog->reloadSliders();
}
// Assuming the LOD adjustment will work: we optimistically reset _avgRenderTime
// to be at middle of target zone. It will drift close to its true value within
// about three few LOD_ADJUST_TIMESCALEs and we'll adjust again as necessary.
float expectedFPS = 0.5f * (getLODIncreaseFPS() + getLODDecreaseFPS());
_avgRenderTime = MSECS_PER_SECOND / expectedFPS;
} }
} }
void LODManager::resetLODAdjust() { void LODManager::resetLODAdjust() {
_fpsAverageStartWindow.reset(); _decreaseFPSExpiry = _increaseFPSExpiry = usecTimestampNow() + LOD_AUTO_ADJUST_PERIOD;
_fpsAverageDownWindow.reset();
_fpsAverageUpWindow.reset();
_lastUpShift = _lastDownShift = usecTimestampNow();
_isDownshifting = false;
} }
const float MIN_DECREASE_FPS = 0.5f; const float MIN_DECREASE_FPS = 0.5f;
@ -206,7 +146,7 @@ float LODManager::getDesktopLODDecreaseFPS() const {
} }
float LODManager::getDesktopLODIncreaseFPS() const { float LODManager::getDesktopLODIncreaseFPS() const {
return glm::max(((float)MSECS_PER_SECOND / _desktopMaxRenderTime) + INCREASE_LOD_GAP, MAX_LIKELY_DESKTOP_FPS); return glm::max(((float)MSECS_PER_SECOND / _desktopMaxRenderTime) + INCREASE_LOD_GAP_FPS, MAX_LIKELY_DESKTOP_FPS);
} }
void LODManager::setHMDLODDecreaseFPS(float fps) { void LODManager::setHMDLODDecreaseFPS(float fps) {
@ -222,7 +162,7 @@ float LODManager::getHMDLODDecreaseFPS() const {
} }
float LODManager::getHMDLODIncreaseFPS() const { float LODManager::getHMDLODIncreaseFPS() const {
return glm::max(((float)MSECS_PER_SECOND / _hmdMaxRenderTime) + INCREASE_LOD_GAP, MAX_LIKELY_HMD_FPS); return glm::max(((float)MSECS_PER_SECOND / _hmdMaxRenderTime) + INCREASE_LOD_GAP_FPS, MAX_LIKELY_HMD_FPS);
} }
QString LODManager::getLODFeedbackText() { QString LODManager::getLODFeedbackText() {

View file

@ -19,29 +19,13 @@
#include <SimpleMovingAverage.h> #include <SimpleMovingAverage.h>
#include <render/Args.h> #include <render/Args.h>
const float DEFAULT_DESKTOP_LOD_DOWN_FPS = 20.0; const float DEFAULT_DESKTOP_LOD_DOWN_FPS = 30.0f;
const float DEFAULT_HMD_LOD_DOWN_FPS = 20.0; const float DEFAULT_HMD_LOD_DOWN_FPS = 45.0f;
const float DEFAULT_DESKTOP_MAX_RENDER_TIME = (float)MSECS_PER_SECOND / DEFAULT_DESKTOP_LOD_DOWN_FPS; // msec const float DEFAULT_DESKTOP_MAX_RENDER_TIME = (float)MSECS_PER_SECOND / DEFAULT_DESKTOP_LOD_DOWN_FPS; // msec
const float DEFAULT_HMD_MAX_RENDER_TIME = (float)MSECS_PER_SECOND / DEFAULT_HMD_LOD_DOWN_FPS; // msec const float DEFAULT_HMD_MAX_RENDER_TIME = (float)MSECS_PER_SECOND / DEFAULT_HMD_LOD_DOWN_FPS; // msec
const float MAX_LIKELY_DESKTOP_FPS = 59.0; // this is essentially, V-synch - 1 fps const float MAX_LIKELY_DESKTOP_FPS = 59.0f; // this is essentially, V-synch - 1 fps
const float MAX_LIKELY_HMD_FPS = 74.0; // this is essentially, V-synch - 1 fps const float MAX_LIKELY_HMD_FPS = 74.0f; // this is essentially, V-synch - 1 fps
const float INCREASE_LOD_GAP = 15.0f; const float INCREASE_LOD_GAP_FPS = 15.0f; // fps
const float START_DELAY_WINDOW_IN_SECS = 3.0f; // wait at least this long after steady state/last upshift to consider downshifts
const float DOWN_SHIFT_WINDOW_IN_SECS = 0.5f;
const float UP_SHIFT_WINDOW_IN_SECS = 2.5f;
const int ASSUMED_FPS = 60;
const quint64 START_SHIFT_ELPASED = USECS_PER_SECOND * START_DELAY_WINDOW_IN_SECS;
const quint64 DOWN_SHIFT_ELPASED = USECS_PER_SECOND * DOWN_SHIFT_WINDOW_IN_SECS; // Consider adjusting LOD down after half a second
const quint64 UP_SHIFT_ELPASED = USECS_PER_SECOND * UP_SHIFT_WINDOW_IN_SECS;
const int START_DELAY_SAMPLES_OF_FRAMES = ASSUMED_FPS * START_DELAY_WINDOW_IN_SECS;
const int DOWN_SHIFT_SAMPLES_OF_FRAMES = ASSUMED_FPS * DOWN_SHIFT_WINDOW_IN_SECS;
const int UP_SHIFT_SAMPLES_OF_FRAMES = ASSUMED_FPS * UP_SHIFT_WINDOW_IN_SECS;
const float ADJUST_LOD_DOWN_BY = 0.9f;
const float ADJUST_LOD_UP_BY = 1.1f;
// The default value DEFAULT_OCTREE_SIZE_SCALE means you can be 400 meters away from a 1 meter object in order to see it (which is ~20:20 vision). // The default value DEFAULT_OCTREE_SIZE_SCALE means you can be 400 meters away from a 1 meter object in order to see it (which is ~20:20 vision).
const float ADJUST_LOD_MAX_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE; const float ADJUST_LOD_MAX_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE;
@ -78,7 +62,7 @@ public:
Q_INVOKABLE float getLODIncreaseFPS(); Q_INVOKABLE float getLODIncreaseFPS();
static bool shouldRender(const RenderArgs* args, const AABox& bounds); static bool shouldRender(const RenderArgs* args, const AABox& bounds);
void autoAdjustLOD(float batchTime, float engineRunTime, float deltaTimeSec); void autoAdjustLOD(float renderTime, float realTimeDelta);
void loadSettings(); void loadSettings();
void saveSettings(); void saveSettings();
@ -92,21 +76,15 @@ private:
LODManager(); LODManager();
bool _automaticLODAdjust = true; bool _automaticLODAdjust = true;
float _avgRenderTime { 0.0 }; float _avgRenderTime { 0.0f };
float _desktopMaxRenderTime { DEFAULT_DESKTOP_MAX_RENDER_TIME }; float _desktopMaxRenderTime { DEFAULT_DESKTOP_MAX_RENDER_TIME };
float _hmdMaxRenderTime { DEFAULT_HMD_MAX_RENDER_TIME }; float _hmdMaxRenderTime { DEFAULT_HMD_MAX_RENDER_TIME };
float _octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE; float _octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE;
int _boundaryLevelAdjust = 0; int _boundaryLevelAdjust = 0;
quint64 _lastDownShift = 0; uint64_t _decreaseFPSExpiry { 0 };
quint64 _lastUpShift = 0; uint64_t _increaseFPSExpiry { 0 };
quint64 _lastStable = 0;
bool _isDownshifting = false; // start out as if we're not downshifting
SimpleMovingAverage _fpsAverageStartWindow = START_DELAY_SAMPLES_OF_FRAMES;
SimpleMovingAverage _fpsAverageDownWindow = DOWN_SHIFT_SAMPLES_OF_FRAMES;
SimpleMovingAverage _fpsAverageUpWindow = UP_SHIFT_SAMPLES_OF_FRAMES;
}; };
#endif // hifi_LODManager_h #endif // hifi_LODManager_h

View file

@ -101,7 +101,7 @@ Menu::Menu() {
auto action = addActionToQMenuAndActionHash(editMenu, MenuOption::RunningScripts, Qt::CTRL | Qt::Key_J); auto action = addActionToQMenuAndActionHash(editMenu, MenuOption::RunningScripts, Qt::CTRL | Qt::Key_J);
connect(action, &QAction::triggered, [] { connect(action, &QAction::triggered, [] {
static const QUrl widgetUrl("hifi/dialogs/RunningScripts.qml"); static const QUrl widgetUrl("hifi/dialogs/RunningScripts.qml");
static const QUrl tabletUrl("../../hifi/dialogs/TabletRunningScripts.qml"); static const QUrl tabletUrl("hifi/dialogs/TabletRunningScripts.qml");
static const QString name("RunningScripts"); static const QString name("RunningScripts");
qApp->showDialog(widgetUrl, tabletUrl, name); qApp->showDialog(widgetUrl, tabletUrl, name);
}); });
@ -338,7 +338,7 @@ Menu::Menu() {
connect(action, &QAction::triggered, [] { connect(action, &QAction::triggered, [] {
auto tablet = DependencyManager::get<TabletScriptingInterface>()->getTablet("com.highfidelity.interface.tablet.system"); auto tablet = DependencyManager::get<TabletScriptingInterface>()->getTablet("com.highfidelity.interface.tablet.system");
auto hmd = DependencyManager::get<HMDScriptingInterface>(); auto hmd = DependencyManager::get<HMDScriptingInterface>();
tablet->loadQMLSource("ControllerSettings.qml"); tablet->loadQMLSource("hifi/tablet/ControllerSettings.qml");
if (!hmd->getShouldShowTablet()) { if (!hmd->getShouldShowTablet()) {
hmd->toggleShouldShowTablet(); hmd->toggleShouldShowTablet();

View file

@ -150,7 +150,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
glm::vec3 getPosition() const override { return _avatar->getWorldPosition(); } glm::vec3 getPosition() const override { return _avatar->getWorldPosition(); }
float getRadius() const override { return std::static_pointer_cast<Avatar>(_avatar)->getBoundingRadius(); } float getRadius() const override { return std::static_pointer_cast<Avatar>(_avatar)->getBoundingRadius(); }
uint64_t getTimestamp() const override { return std::static_pointer_cast<Avatar>(_avatar)->getLastRenderUpdateTime(); } uint64_t getTimestamp() const override { return std::static_pointer_cast<Avatar>(_avatar)->getLastRenderUpdateTime(); }
const AvatarSharedPointer& getAvatar() const { return _avatar; } AvatarSharedPointer getAvatar() const { return _avatar; }
private: private:
AvatarSharedPointer _avatar; AvatarSharedPointer _avatar;
}; };
@ -185,7 +185,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
render::Transaction transaction; render::Transaction transaction;
while (!sortedAvatars.empty()) { while (!sortedAvatars.empty()) {
const SortableAvatar& sortData = sortedAvatars.top(); const SortableAvatar& sortData = sortedAvatars.top();
const auto& avatar = std::static_pointer_cast<Avatar>(sortData.getAvatar()); const auto avatar = std::static_pointer_cast<Avatar>(sortData.getAvatar());
bool ignoring = DependencyManager::get<NodeList>()->isPersonalMutingNode(avatar->getID()); bool ignoring = DependencyManager::get<NodeList>()->isPersonalMutingNode(avatar->getID());
if (ignoring) { if (ignoring) {
@ -239,7 +239,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
sortedAvatars.pop(); sortedAvatars.pop();
while (inView && !sortedAvatars.empty()) { while (inView && !sortedAvatars.empty()) {
const SortableAvatar& newSortData = sortedAvatars.top(); const SortableAvatar& newSortData = sortedAvatars.top();
const auto& newAvatar = std::static_pointer_cast<Avatar>(newSortData.getAvatar()); const auto newAvatar = std::static_pointer_cast<Avatar>(newSortData.getAvatar());
inView = newSortData.getPriority() > OUT_OF_VIEW_THRESHOLD; inView = newSortData.getPriority() > OUT_OF_VIEW_THRESHOLD;
if (inView && newAvatar->hasNewJointData()) { if (inView && newAvatar->hasNewJointData()) {
numAVatarsNotUpdated++; numAVatarsNotUpdated++;

View file

@ -61,7 +61,7 @@ void Ledger::send(const QString& endpoint, const QString& success, const QString
void Ledger::signedSend(const QString& propertyName, const QByteArray& text, const QString& key, const QString& endpoint, const QString& success, const QString& fail, const bool controlled_failure) { void Ledger::signedSend(const QString& propertyName, const QByteArray& text, const QString& key, const QString& endpoint, const QString& success, const QString& fail, const bool controlled_failure) {
auto wallet = DependencyManager::get<Wallet>(); auto wallet = DependencyManager::get<Wallet>();
QString signature = key.isEmpty() ? "" : wallet->signWithKey(text, key); QString signature = wallet->signWithKey(text, key);
QJsonObject request; QJsonObject request;
request[propertyName] = QString(text); request[propertyName] = QString(text);
if (!controlled_failure) { if (!controlled_failure) {

View file

@ -16,9 +16,7 @@
#include "Wallet.h" #include "Wallet.h"
#include <AccountManager.h> #include <AccountManager.h>
HIFI_QML_DEF(QmlCommerce) QmlCommerce::QmlCommerce() {
QmlCommerce::QmlCommerce(QQuickItem* parent) : OffscreenQmlDialog(parent) {
auto ledger = DependencyManager::get<Ledger>(); auto ledger = DependencyManager::get<Ledger>();
auto wallet = DependencyManager::get<Wallet>(); auto wallet = DependencyManager::get<Wallet>();
connect(ledger.data(), &Ledger::buyResult, this, &QmlCommerce::buyResult); connect(ledger.data(), &Ledger::buyResult, this, &QmlCommerce::buyResult);

View file

@ -16,16 +16,14 @@
#define hifi_QmlCommerce_h #define hifi_QmlCommerce_h
#include <QJsonObject> #include <QJsonObject>
#include <OffscreenQmlDialog.h>
#include <QPixmap> #include <QPixmap>
class QmlCommerce : public OffscreenQmlDialog { class QmlCommerce : public QObject {
Q_OBJECT Q_OBJECT
HIFI_QML_DECL
public: public:
QmlCommerce(QQuickItem* parent = nullptr); QmlCommerce();
signals: signals:
void walletStatusResult(uint walletStatus); void walletStatusResult(uint walletStatus);

View file

@ -548,13 +548,16 @@ QStringList Wallet::listPublicKeys() {
// the horror of code pages and so on (changing the bytes) by just returning a base64 // the horror of code pages and so on (changing the bytes) by just returning a base64
// encoded string representing the signature (suitable for http, etc...) // encoded string representing the signature (suitable for http, etc...)
QString Wallet::signWithKey(const QByteArray& text, const QString& key) { QString Wallet::signWithKey(const QByteArray& text, const QString& key) {
qCInfo(commerce) << "Signing text" << text << "with key" << key;
EC_KEY* ecPrivateKey = NULL; EC_KEY* ecPrivateKey = NULL;
auto keyFilePathString = keyFilePath().toStdString();
if ((ecPrivateKey = readPrivateKey(keyFilePath().toStdString().c_str()))) { if ((ecPrivateKey = readPrivateKey(keyFilePath().toStdString().c_str()))) {
unsigned char* sig = new unsigned char[ECDSA_size(ecPrivateKey)]; unsigned char* sig = new unsigned char[ECDSA_size(ecPrivateKey)];
unsigned int signatureBytes = 0; unsigned int signatureBytes = 0;
qCInfo(commerce) << "Hashing and signing plaintext" << text << "with key at address" << ecPrivateKey;
QByteArray hashedPlaintext = QCryptographicHash::hash(text, QCryptographicHash::Sha256); QByteArray hashedPlaintext = QCryptographicHash::hash(text, QCryptographicHash::Sha256);
@ -747,12 +750,10 @@ void Wallet::handleChallengeOwnershipPacket(QSharedPointer<ReceivedMessage> pack
} }
EC_KEY_free(ec); EC_KEY_free(ec);
QByteArray ba = sig.toLocal8Bit();
const char *sigChar = ba.data();
QByteArray textByteArray; QByteArray textByteArray;
if (status > -1) { if (status > -1) {
textByteArray = QByteArray(sigChar, (int) strlen(sigChar)); textByteArray = sig.toUtf8();
} }
textByteArraySize = textByteArray.size(); textByteArraySize = textByteArray.size();
int certIDSize = certID.size(); int certIDSize = certID.size();

View file

@ -31,7 +31,7 @@
#include "scripting/HMDScriptingInterface.h" #include "scripting/HMDScriptingInterface.h"
static const QVariant TABLET_ADDRESS_DIALOG = "TabletAddressDialog.qml"; static const QVariant TABLET_ADDRESS_DIALOG = "hifi/tablet/TabletAddressDialog.qml";
template<typename T> template<typename T>
void DialogsManager::maybeCreateDialog(QPointer<T>& member) { void DialogsManager::maybeCreateDialog(QPointer<T>& member) {
if (!member) { if (!member) {
@ -91,7 +91,7 @@ void DialogsManager::setDomainConnectionFailureVisibility(bool visible) {
ConnectionFailureDialog::hide(); ConnectionFailureDialog::hide();
} }
} else { } else {
static const QUrl url("../../dialogs/TabletConnectionFailureDialog.qml"); static const QUrl url("dialogs/TabletConnectionFailureDialog.qml");
auto hmd = DependencyManager::get<HMDScriptingInterface>(); auto hmd = DependencyManager::get<HMDScriptingInterface>();
if (visible) { if (visible) {
tablet->initialScreen(url); tablet->initialScreen(url);

View file

@ -46,7 +46,7 @@ void LoginDialog::showWithSelection()
if (tablet->getToolbarMode()) { if (tablet->getToolbarMode()) {
LoginDialog::show(); LoginDialog::show();
} else { } else {
static const QUrl url("../../dialogs/TabletLoginDialog.qml"); static const QUrl url("dialogs/TabletLoginDialog.qml");
tablet->initialScreen(url); tablet->initialScreen(url);
if (!hmd->getShouldShowTablet()) { if (!hmd->getShouldShowTablet()) {
hmd->openTablet(); hmd->openTablet();

View file

@ -266,7 +266,7 @@ void ContextOverlayInterface::contextOverlays_hoverLeaveEntity(const EntityItemI
} }
} }
static const QString INSPECTION_CERTIFICATE_QML_PATH = qApp->applicationDirPath() + "../../../qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml"; static const QString INSPECTION_CERTIFICATE_QML_PATH = "hifi/commerce/inspectionCertificate/InspectionCertificate.qml";
void ContextOverlayInterface::openInspectionCertificate() { void ContextOverlayInterface::openInspectionCertificate() {
// lets open the tablet to the inspection certificate QML // lets open the tablet to the inspection certificate QML
if (!_currentEntityWithContextOverlay.isNull() && _entityMarketplaceID.length() > 0) { if (!_currentEntityWithContextOverlay.isNull() && _entityMarketplaceID.length() > 0) {

View file

@ -24,7 +24,6 @@ ModelOverlay::ModelOverlay()
: _model(std::make_shared<Model>(nullptr, this)), : _model(std::make_shared<Model>(nullptr, this)),
_modelTextures(QVariantMap()) _modelTextures(QVariantMap())
{ {
_model->init();
_model->setLoadingPriority(_loadPriority); _model->setLoadingPriority(_loadPriority);
_isLoaded = false; _isLoaded = false;
} }
@ -38,7 +37,6 @@ ModelOverlay::ModelOverlay(const ModelOverlay* modelOverlay) :
_scaleToFit(modelOverlay->_scaleToFit), _scaleToFit(modelOverlay->_scaleToFit),
_loadPriority(modelOverlay->_loadPriority) _loadPriority(modelOverlay->_loadPriority)
{ {
_model->init();
_model->setLoadingPriority(_loadPriority); _model->setLoadingPriority(_loadPriority);
if (_url.isValid()) { if (_url.isValid()) {
_updateModel = true; _updateModel = true;

View file

@ -200,7 +200,6 @@ void Web3DOverlay::setupQmlSurface() {
_webSurface->getSurfaceContext()->setContextProperty("fileDialogHelper", new FileDialogHelper()); _webSurface->getSurfaceContext()->setContextProperty("fileDialogHelper", new FileDialogHelper());
_webSurface->getSurfaceContext()->setContextProperty("MyAvatar", DependencyManager::get<AvatarManager>()->getMyAvatar().get()); _webSurface->getSurfaceContext()->setContextProperty("MyAvatar", DependencyManager::get<AvatarManager>()->getMyAvatar().get());
_webSurface->getSurfaceContext()->setContextProperty("ScriptDiscoveryService", DependencyManager::get<ScriptEngines>().data()); _webSurface->getSurfaceContext()->setContextProperty("ScriptDiscoveryService", DependencyManager::get<ScriptEngines>().data());
_webSurface->getSurfaceContext()->setContextProperty("Tablet", DependencyManager::get<TabletScriptingInterface>().data());
_webSurface->getSurfaceContext()->setContextProperty("Assets", DependencyManager::get<AssetMappingsScriptingInterface>().data()); _webSurface->getSurfaceContext()->setContextProperty("Assets", DependencyManager::get<AssetMappingsScriptingInterface>().data());
_webSurface->getSurfaceContext()->setContextProperty("LODManager", DependencyManager::get<LODManager>().data()); _webSurface->getSurfaceContext()->setContextProperty("LODManager", DependencyManager::get<LODManager>().data());
_webSurface->getSurfaceContext()->setContextProperty("OctreeStats", DependencyManager::get<OctreeStatsProvider>().data()); _webSurface->getSurfaceContext()->setContextProperty("OctreeStats", DependencyManager::get<OctreeStatsProvider>().data());
@ -220,9 +219,6 @@ void Web3DOverlay::setupQmlSurface() {
_webSurface->getSurfaceContext()->setContextProperty("pathToFonts", "../../"); _webSurface->getSurfaceContext()->setContextProperty("pathToFonts", "../../");
// Tablet inteference with Tablet.qml. Need to avoid this in QML space
_webSurface->getSurfaceContext()->setContextProperty("tabletInterface", DependencyManager::get<TabletScriptingInterface>().data());
tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", _webSurface.data()); tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", _webSurface.data());
// mark the TabletProxy object as cpp ownership. // mark the TabletProxy object as cpp ownership.
QObject* tablet = tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"); QObject* tablet = tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system");

View file

@ -138,7 +138,6 @@ Avatar::~Avatar() {
void Avatar::init() { void Avatar::init() {
getHead()->init(); getHead()->init();
_skeletonModel->init();
_initialized = true; _initialized = true;
} }

View file

@ -679,17 +679,13 @@ void OpenGLDisplayPlugin::internalPresent() {
void OpenGLDisplayPlugin::present() { void OpenGLDisplayPlugin::present() {
auto frameId = (uint64_t)presentCount(); auto frameId = (uint64_t)presentCount();
PROFILE_RANGE_EX(render, __FUNCTION__, 0xffffff00, frameId) PROFILE_RANGE_EX(render, __FUNCTION__, 0xffffff00, frameId)
uint64_t startPresent = usecTimestampNow();
{ {
PROFILE_RANGE_EX(render, "updateFrameData", 0xff00ff00, frameId) PROFILE_RANGE_EX(render, "updateFrameData", 0xff00ff00, frameId)
updateFrameData(); updateFrameData();
} }
incrementPresentCount(); incrementPresentCount();
{
PROFILE_RANGE_EX(render, "recycle", 0xff00ff00, frameId)
_gpuContext->recycle();
}
if (_currentFrame) { if (_currentFrame) {
{ {
withPresentThreadLock([&] { withPresentThreadLock([&] {
@ -718,6 +714,7 @@ void OpenGLDisplayPlugin::present() {
gpu::Backend::freeGPUMemSize.set(gpu::gl::getFreeDedicatedMemory()); gpu::Backend::freeGPUMemSize.set(gpu::gl::getFreeDedicatedMemory());
} }
_movingAveragePresent.addSample((float)(usecTimestampNow() - startPresent));
} }
float OpenGLDisplayPlugin::newFramePresentRate() const { float OpenGLDisplayPlugin::newFramePresentRate() const {

View file

@ -349,7 +349,7 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene
float getRadius() const override { return 0.5f * _renderer->getEntity()->getQueryAACube().getScale(); } float getRadius() const override { return 0.5f * _renderer->getEntity()->getQueryAACube().getScale(); }
uint64_t getTimestamp() const override { return _renderer->getUpdateTime(); } uint64_t getTimestamp() const override { return _renderer->getUpdateTime(); }
const EntityRendererPointer& getRenderer() const { return _renderer; } EntityRendererPointer getRenderer() const { return _renderer; }
private: private:
EntityRendererPointer _renderer; EntityRendererPointer _renderer;
}; };
@ -382,7 +382,7 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene
std::unordered_map<EntityItemID, EntityRendererPointer>::iterator itr; std::unordered_map<EntityItemID, EntityRendererPointer>::iterator itr;
size_t numSorted = sortedRenderables.size(); size_t numSorted = sortedRenderables.size();
while (!sortedRenderables.empty() && usecTimestampNow() < expiry) { while (!sortedRenderables.empty() && usecTimestampNow() < expiry) {
const EntityRendererPointer& renderable = sortedRenderables.top().getRenderer(); const auto renderable = sortedRenderables.top().getRenderer();
renderable->updateInScene(scene, transaction); renderable->updateInScene(scene, transaction);
_renderablesToUpdate.erase(renderable->getEntity()->getID()); _renderablesToUpdate.erase(renderable->getEntity()->getID());
sortedRenderables.pop(); sortedRenderables.pop();

View file

@ -993,19 +993,15 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) {
} }
{ {
// the current frame is set on the server in update() in ModelEntityItem.cpp float currentFrame = fmod(entity->getAnimationCurrentFrame(), (float)(frameCount));
int animationCurrentFrame = (int)(glm::floor(entity->getAnimationCurrentFrame())); if (currentFrame < 0.0f) {
currentFrame += (float)frameCount;
// in the case where the last frame is greater than the framecount then clamp
// it to the end of the animation until it loops around.
if (animationCurrentFrame < 0 || animationCurrentFrame > frameCount) {
animationCurrentFrame = 0;
} }
int currentIntegerFrame = (int)(glm::floor(currentFrame));
if (animationCurrentFrame == _lastKnownCurrentFrame) { if (currentIntegerFrame == _lastKnownCurrentFrame) {
return; return;
} }
_lastKnownCurrentFrame = animationCurrentFrame; _lastKnownCurrentFrame = currentIntegerFrame;
} }
if (_jointMapping.size() != _model->getJointStateCount()) { if (_jointMapping.size() != _model->getJointStateCount()) {
@ -1213,7 +1209,6 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
connect(model.get(), &Model::requestRenderUpdate, this, &ModelEntityRenderer::requestRenderUpdate); connect(model.get(), &Model::requestRenderUpdate, this, &ModelEntityRenderer::requestRenderUpdate);
connect(entity.get(), &RenderableModelEntityItem::requestCollisionGeometryUpdate, this, &ModelEntityRenderer::flagForCollisionGeometryUpdate); connect(entity.get(), &RenderableModelEntityItem::requestCollisionGeometryUpdate, this, &ModelEntityRenderer::flagForCollisionGeometryUpdate);
model->setLoadingPriority(EntityTreeRenderer::getEntityLoadingPriority(*entity)); model->setLoadingPriority(EntityTreeRenderer::getEntityLoadingPriority(*entity));
model->init();
entity->setModel(model); entity->setModel(model);
withWriteLock([&] { _model = model; }); withWriteLock([&] { _model = model; });
} }

View file

@ -303,6 +303,7 @@ void PolyLineEntityRenderer::doRender(RenderArgs* args) {
batch.setInputBuffer(0, _verticesBuffer, 0, sizeof(Vertex)); batch.setInputBuffer(0, _verticesBuffer, 0, sizeof(Vertex));
#ifndef POLYLINE_ENTITY_USE_FADE_EFFECT #ifndef POLYLINE_ENTITY_USE_FADE_EFFECT
// glColor4f must be called after setInputFormat if it must be taken into account
if (_isFading) { if (_isFading) {
batch._glColor4f(1.0f, 1.0f, 1.0f, Interpolate::calculateFadeRatio(_fadeStartTime)); batch._glColor4f(1.0f, 1.0f, 1.0f, Interpolate::calculateFadeRatio(_fadeStartTime));
} else { } else {

View file

@ -137,11 +137,10 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
}); });
if (proceduralRender) { if (proceduralRender) {
batch._glColor4f(outColor.r, outColor.g, outColor.b, outColor.a);
if (render::ShapeKey(args->_globalShapeKey).isWireframe()) { if (render::ShapeKey(args->_globalShapeKey).isWireframe()) {
geometryCache->renderWireShape(batch, geometryShape); geometryCache->renderWireShape(batch, geometryShape, outColor);
} else { } else {
geometryCache->renderShape(batch, geometryShape); geometryCache->renderShape(batch, geometryShape, outColor);
} }
} else { } else {
// FIXME, support instanced multi-shape rendering using multidraw indirect // FIXME, support instanced multi-shape rendering using multidraw indirect

Some files were not shown because too many files have changed in this diff Show more