mirror of
https://github.com/overte-org/overte.git
synced 2025-08-04 14:29:35 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into commerce_SendMoneyNearbyParticle
This commit is contained in:
commit
268c12e47a
45 changed files with 431 additions and 31174 deletions
|
@ -453,7 +453,7 @@ void EntityServer::domainSettingsRequestFailed() {
|
|||
void EntityServer::startDynamicDomainVerification() {
|
||||
qCDebug(entities) << "Starting Dynamic Domain Verification...";
|
||||
|
||||
QString thisDomainID = DependencyManager::get<AddressManager>()->getDomainId().remove(QRegExp("\\{|\\}"));
|
||||
QString thisDomainID = DependencyManager::get<AddressManager>()->getDomainID().remove(QRegExp("\\{|\\}"));
|
||||
|
||||
EntityTreePointer tree = std::static_pointer_cast<EntityTree>(_tree);
|
||||
QHash<QString, EntityItemID> localMap(tree->getEntityCertificateIDMap());
|
||||
|
|
|
@ -32,6 +32,12 @@ Original.Button {
|
|||
Tablet.playSound(TabletEnums.ButtonHover);
|
||||
}
|
||||
}
|
||||
|
||||
onFocusChanged: {
|
||||
if (focus) {
|
||||
Tablet.playSound(TabletEnums.ButtonHover);
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
Tablet.playSound(TabletEnums.ButtonClick);
|
||||
|
@ -59,6 +65,8 @@ Original.Button {
|
|||
hifi.buttons.pressedColor[control.color]
|
||||
} else if (control.hovered) {
|
||||
hifi.buttons.hoveredColor[control.color]
|
||||
} else if (!control.hovered && control.focus) {
|
||||
hifi.buttons.focusedColor[control.color]
|
||||
} else {
|
||||
hifi.buttons.colorStart[control.color]
|
||||
}
|
||||
|
@ -73,6 +81,8 @@ Original.Button {
|
|||
hifi.buttons.pressedColor[control.color]
|
||||
} else if (control.hovered) {
|
||||
hifi.buttons.hoveredColor[control.color]
|
||||
} else if (!control.hovered && control.focus) {
|
||||
hifi.buttons.focusedColor[control.color]
|
||||
} else {
|
||||
hifi.buttons.colorFinish[control.color]
|
||||
}
|
||||
|
|
|
@ -31,6 +31,12 @@ Original.Button {
|
|||
}
|
||||
}
|
||||
|
||||
onFocusChanged: {
|
||||
if (focus) {
|
||||
Tablet.playSound(TabletEnums.ButtonHover);
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
Tablet.playSound(TabletEnums.ButtonClick);
|
||||
}
|
||||
|
@ -50,6 +56,8 @@ Original.Button {
|
|||
hifi.buttons.pressedColor[control.color]
|
||||
} else if (control.hovered) {
|
||||
hifi.buttons.hoveredColor[control.color]
|
||||
} else if (!control.hovered && control.focus) {
|
||||
hifi.buttons.focusedColor[control.color]
|
||||
} else {
|
||||
hifi.buttons.colorStart[control.color]
|
||||
}
|
||||
|
@ -64,6 +72,8 @@ Original.Button {
|
|||
hifi.buttons.pressedColor[control.color]
|
||||
} else if (control.hovered) {
|
||||
hifi.buttons.hoveredColor[control.color]
|
||||
} else if (!control.hovered && control.focus) {
|
||||
hifi.buttons.focusedColor[control.color]
|
||||
} else {
|
||||
hifi.buttons.colorFinish[control.color]
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ TableView {
|
|||
size: hifi.fontSizes.tableHeadingIcon
|
||||
anchors {
|
||||
left: titleText.right
|
||||
leftMargin: -hifi.fontSizes.tableHeadingIcon / 3 - (centerHeaderText ? 5 : 0)
|
||||
leftMargin: -hifi.fontSizes.tableHeadingIcon / 3 - (centerHeaderText ? 15 : 10)
|
||||
right: parent.right
|
||||
rightMargin: hifi.dimensions.tablePadding
|
||||
verticalCenter: titleText.verticalCenter
|
||||
|
|
|
@ -110,7 +110,17 @@ ModalWindow {
|
|||
}
|
||||
});
|
||||
|
||||
fileTableView.forceActiveFocus();
|
||||
focusTimer.start();
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: focusTimer
|
||||
interval: 10
|
||||
running: false
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
fileTableView.contentItem.forceActiveFocus();
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
|
@ -130,7 +140,9 @@ ModalWindow {
|
|||
drag.target: root
|
||||
onClicked: {
|
||||
d.clearSelection();
|
||||
frame.forceActiveFocus(); // Defocus text field so that the keyboard gets hidden.
|
||||
// Defocus text field so that the keyboard gets hidden.
|
||||
// Clicking also breaks keyboard navigation apart from backtabbing to cancel
|
||||
frame.forceActiveFocus();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,6 +162,11 @@ ModalWindow {
|
|||
size: 30
|
||||
enabled: fileTableModel.parentFolder && fileTableModel.parentFolder !== ""
|
||||
onClicked: d.navigateUp();
|
||||
Keys.onReturnPressed: { d.navigateUp(); }
|
||||
KeyNavigation.tab: homeButton
|
||||
KeyNavigation.backtab: upButton
|
||||
KeyNavigation.left: upButton
|
||||
KeyNavigation.right: homeButton
|
||||
}
|
||||
|
||||
GlyphButton {
|
||||
|
@ -160,6 +177,10 @@ ModalWindow {
|
|||
width: height
|
||||
enabled: d.homeDestination ? true : false
|
||||
onClicked: d.navigateHome();
|
||||
Keys.onReturnPressed: { d.navigateHome(); }
|
||||
KeyNavigation.tab: fileTableView.contentItem
|
||||
KeyNavigation.backtab: upButton
|
||||
KeyNavigation.left: upButton
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -228,9 +249,15 @@ ModalWindow {
|
|||
d.currentSelectionUrl = helper.pathToUrl(currentText);
|
||||
}
|
||||
fileTableModel.folder = folder;
|
||||
fileTableView.forceActiveFocus();
|
||||
}
|
||||
}
|
||||
|
||||
KeyNavigation.up: fileTableView.contentItem
|
||||
KeyNavigation.down: fileTableView.contentItem
|
||||
KeyNavigation.tab: fileTableView.contentItem
|
||||
KeyNavigation.backtab: fileTableView.contentItem
|
||||
KeyNavigation.left: fileTableView.contentItem
|
||||
KeyNavigation.right: fileTableView.contentItem
|
||||
}
|
||||
|
||||
QtObject {
|
||||
|
@ -483,7 +510,6 @@ ModalWindow {
|
|||
}
|
||||
headerVisible: !selectDirectory
|
||||
onDoubleClicked: navigateToRow(row);
|
||||
focus: true
|
||||
Keys.onReturnPressed: navigateToCurrentRow();
|
||||
Keys.onEnterPressed: navigateToCurrentRow();
|
||||
|
||||
|
@ -560,7 +586,7 @@ ModalWindow {
|
|||
resizable: true
|
||||
}
|
||||
TableViewColumn {
|
||||
id: fileMofifiedColumn
|
||||
id: fileModifiedColumn
|
||||
role: "fileModified"
|
||||
title: "Date"
|
||||
width: 0.3 * fileTableView.width
|
||||
|
@ -571,7 +597,7 @@ ModalWindow {
|
|||
TableViewColumn {
|
||||
role: "fileSize"
|
||||
title: "Size"
|
||||
width: fileTableView.width - fileNameColumn.width - fileMofifiedColumn.width
|
||||
width: fileTableView.width - fileNameColumn.width - fileModifiedColumn.width
|
||||
movable: false
|
||||
resizable: true
|
||||
visible: !selectDirectory
|
||||
|
@ -649,6 +675,8 @@ ModalWindow {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
KeyNavigation.tab: root.saveDialog ? currentSelection : openButton
|
||||
}
|
||||
|
||||
TextField {
|
||||
|
@ -665,6 +693,10 @@ ModalWindow {
|
|||
activeFocusOnTab: !readOnly
|
||||
onActiveFocusChanged: if (activeFocus) { selectAll(); }
|
||||
onAccepted: okAction.trigger();
|
||||
KeyNavigation.up: fileTableView.contentItem
|
||||
KeyNavigation.down: openButton
|
||||
KeyNavigation.tab: openButton
|
||||
KeyNavigation.backtab: fileTableView.contentItem
|
||||
}
|
||||
|
||||
FileTypeSelection {
|
||||
|
@ -675,8 +707,6 @@ ModalWindow {
|
|||
right: parent.right
|
||||
}
|
||||
visible: !selectDirectory && filtersCount > 1
|
||||
KeyNavigation.left: fileTableView
|
||||
KeyNavigation.right: openButton
|
||||
}
|
||||
|
||||
Keyboard {
|
||||
|
@ -704,18 +734,18 @@ ModalWindow {
|
|||
color: hifi.buttons.blue
|
||||
action: okAction
|
||||
Keys.onReturnPressed: okAction.trigger()
|
||||
KeyNavigation.up: selectionType
|
||||
KeyNavigation.left: selectionType
|
||||
KeyNavigation.right: cancelButton
|
||||
KeyNavigation.up: root.saveDialog ? currentSelection : fileTableView.contentItem
|
||||
KeyNavigation.tab: cancelButton
|
||||
}
|
||||
|
||||
Button {
|
||||
id: cancelButton
|
||||
action: cancelAction
|
||||
KeyNavigation.up: selectionType
|
||||
Keys.onReturnPressed: { cancelAction.trigger() }
|
||||
KeyNavigation.left: openButton
|
||||
KeyNavigation.right: fileTableView.contentItem
|
||||
Keys.onReturnPressed: { canceled(); root.enabled = false }
|
||||
KeyNavigation.up: root.saveDialog ? currentSelection : fileTableView.contentItem
|
||||
KeyNavigation.backtab: openButton
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,16 @@ ModalWindow {
|
|||
return OffscreenUi.waitForMessageBoxResult(root);
|
||||
}
|
||||
|
||||
Keys.onRightPressed: if (defaultButton === OriginalDialogs.StandardButton.Yes) {
|
||||
yesButton.forceActiveFocus()
|
||||
} else if (defaultButton === OriginalDialogs.StandardButton.Ok) {
|
||||
okButton.forceActiveFocus()
|
||||
}
|
||||
Keys.onTabPressed: if (defaultButton === OriginalDialogs.StandardButton.Yes) {
|
||||
yesButton.forceActiveFocus()
|
||||
} else if (defaultButton === OriginalDialogs.StandardButton.Ok) {
|
||||
okButton.forceActiveFocus()
|
||||
}
|
||||
property alias detailedText: detailedText.text
|
||||
property alias text: mainTextContainer.text
|
||||
property alias informativeText: informativeTextContainer.text
|
||||
|
@ -47,7 +57,6 @@ ModalWindow {
|
|||
onIconChanged: updateIcon();
|
||||
property int defaultButton: OriginalDialogs.StandardButton.NoButton;
|
||||
property int clickedButton: OriginalDialogs.StandardButton.NoButton;
|
||||
focus: defaultButton === OriginalDialogs.StandardButton.NoButton
|
||||
|
||||
property int titleWidth: 0
|
||||
onTitleWidthChanged: d.resize();
|
||||
|
@ -134,16 +143,35 @@ ModalWindow {
|
|||
MessageDialogButton { dialog: root; text: qsTr("Reset"); button: OriginalDialogs.StandardButton.Reset; }
|
||||
MessageDialogButton { dialog: root; text: qsTr("Discard"); button: OriginalDialogs.StandardButton.Discard; }
|
||||
MessageDialogButton { dialog: root; text: qsTr("No to All"); button: OriginalDialogs.StandardButton.NoToAll; }
|
||||
MessageDialogButton { dialog: root; text: qsTr("No"); button: OriginalDialogs.StandardButton.No; }
|
||||
MessageDialogButton {
|
||||
id: noButton
|
||||
dialog: root
|
||||
text: qsTr("No")
|
||||
button: OriginalDialogs.StandardButton.No
|
||||
KeyNavigation.left: yesButton
|
||||
KeyNavigation.backtab: yesButton
|
||||
}
|
||||
MessageDialogButton { dialog: root; text: qsTr("Yes to All"); button: OriginalDialogs.StandardButton.YesToAll; }
|
||||
MessageDialogButton { dialog: root; text: qsTr("Yes"); button: OriginalDialogs.StandardButton.Yes; }
|
||||
MessageDialogButton {
|
||||
id: yesButton
|
||||
dialog: root
|
||||
text: qsTr("Yes")
|
||||
button: OriginalDialogs.StandardButton.Yes
|
||||
KeyNavigation.right: noButton
|
||||
KeyNavigation.tab: noButton
|
||||
}
|
||||
MessageDialogButton { dialog: root; text: qsTr("Apply"); button: OriginalDialogs.StandardButton.Apply; }
|
||||
MessageDialogButton { dialog: root; text: qsTr("Ignore"); button: OriginalDialogs.StandardButton.Ignore; }
|
||||
MessageDialogButton { dialog: root; text: qsTr("Retry"); button: OriginalDialogs.StandardButton.Retry; }
|
||||
MessageDialogButton { dialog: root; text: qsTr("Save All"); button: OriginalDialogs.StandardButton.SaveAll; }
|
||||
MessageDialogButton { dialog: root; text: qsTr("Save"); button: OriginalDialogs.StandardButton.Save; }
|
||||
MessageDialogButton { dialog: root; text: qsTr("Open"); button: OriginalDialogs.StandardButton.Open; }
|
||||
MessageDialogButton { dialog: root; text: qsTr("OK"); button: OriginalDialogs.StandardButton.Ok; }
|
||||
MessageDialogButton {
|
||||
id: okButton
|
||||
dialog: root
|
||||
text: qsTr("OK")
|
||||
button: OriginalDialogs.StandardButton.Ok
|
||||
}
|
||||
|
||||
Button {
|
||||
id: moreButton
|
||||
|
@ -230,12 +258,6 @@ ModalWindow {
|
|||
event.accepted = true
|
||||
root.click(OriginalDialogs.StandardButton.Cancel)
|
||||
break
|
||||
|
||||
case Qt.Key_Enter:
|
||||
case Qt.Key_Return:
|
||||
event.accepted = true
|
||||
root.click(root.defaultButton)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,19 +95,19 @@ ModalWindow {
|
|||
TextField {
|
||||
id: textResult
|
||||
label: root.label
|
||||
focus: items ? false : true
|
||||
visible: items ? false : true
|
||||
anchors {
|
||||
left: parent.left;
|
||||
right: parent.right;
|
||||
bottom: parent.bottom
|
||||
}
|
||||
KeyNavigation.down: acceptButton
|
||||
KeyNavigation.tab: acceptButton
|
||||
}
|
||||
|
||||
ComboBox {
|
||||
id: comboBox
|
||||
label: root.label
|
||||
focus: true
|
||||
visible: items ? true : false
|
||||
anchors {
|
||||
left: parent.left
|
||||
|
@ -115,6 +115,8 @@ ModalWindow {
|
|||
bottom: parent.bottom
|
||||
}
|
||||
model: items ? items : []
|
||||
KeyNavigation.down: acceptButton
|
||||
KeyNavigation.tab: acceptButton
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,7 +137,6 @@ ModalWindow {
|
|||
|
||||
Flow {
|
||||
id: buttons
|
||||
focus: true
|
||||
spacing: hifi.dimensions.contentSpacing.x
|
||||
onHeightChanged: d.resize(); onWidthChanged: d.resize();
|
||||
layoutDirection: Qt.RightToLeft
|
||||
|
@ -145,8 +146,21 @@ ModalWindow {
|
|||
margins: 0
|
||||
bottomMargin: hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
Button { action: cancelAction }
|
||||
Button { action: acceptAction }
|
||||
Button {
|
||||
id: cancelButton
|
||||
action: cancelAction
|
||||
KeyNavigation.left: acceptButton
|
||||
KeyNavigation.up: items ? comboBox : textResult
|
||||
KeyNavigation.backtab: acceptButton
|
||||
}
|
||||
Button {
|
||||
id: acceptButton
|
||||
action: acceptAction
|
||||
KeyNavigation.right: cancelButton
|
||||
KeyNavigation.up: items ? comboBox : textResult
|
||||
KeyNavigation.tab: cancelButton
|
||||
KeyNavigation.backtab: items ? comboBox : textResult
|
||||
}
|
||||
}
|
||||
|
||||
Action {
|
||||
|
@ -184,7 +198,13 @@ ModalWindow {
|
|||
|
||||
case Qt.Key_Return:
|
||||
case Qt.Key_Enter:
|
||||
acceptAction.trigger()
|
||||
if (acceptButton.focus) {
|
||||
acceptAction.trigger()
|
||||
} else if (cancelButton.focus) {
|
||||
cancelAction.trigger()
|
||||
} else if (comboBox.focus || comboBox.popup.focus) {
|
||||
comboBox.showList()
|
||||
}
|
||||
event.accepted = true;
|
||||
break;
|
||||
}
|
||||
|
@ -194,6 +214,10 @@ ModalWindow {
|
|||
keyboardEnabled = HMD.active;
|
||||
updateIcon();
|
||||
d.resize();
|
||||
textResult.forceActiveFocus();
|
||||
if (items) {
|
||||
comboBox.forceActiveFocus()
|
||||
} else {
|
||||
textResult.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,10 +16,21 @@ import "../../controls-uit"
|
|||
|
||||
Button {
|
||||
property var dialog;
|
||||
property int button: StandardButton.NoButton;
|
||||
property int button: StandardButton.Ok;
|
||||
|
||||
color: dialog.defaultButton === button ? hifi.buttons.blue : hifi.buttons.white
|
||||
focus: dialog.defaultButton === button
|
||||
color: focus ? hifi.buttons.blue : hifi.buttons.white
|
||||
onClicked: dialog.click(button)
|
||||
visible: dialog.buttons & button
|
||||
Keys.onPressed: {
|
||||
if (!focus) {
|
||||
return
|
||||
}
|
||||
switch (event.key) {
|
||||
case Qt.Key_Enter:
|
||||
case Qt.Key_Return:
|
||||
event.accepted = true
|
||||
dialog.click(button)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -219,6 +219,7 @@ Item {
|
|||
readonly property var colorFinish: [ colors.lightGrayText, colors.blueAccent, "#94132e", colors.black, Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0) ]
|
||||
readonly property var hoveredColor: [ colorStart[white], colorStart[blue], colorStart[red], colorFinish[black], colorStart[none], colorStart[noneBorderless], colorStart[noneBorderlessWhite], colorStart[noneBorderlessGray] ]
|
||||
readonly property var pressedColor: [ colorFinish[white], colorFinish[blue], colorFinish[red], colorStart[black], colorStart[none], colorStart[noneBorderless], colorStart[noneBorderlessWhite], colorStart[noneBorderlessGray] ]
|
||||
readonly property var focusedColor: [ colors.lightGray50, colors.blueAccent, colors.redAccent, colors.darkGray, colorStart[none], colorStart[noneBorderless], colorStart[noneBorderlessWhite], colorStart[noneBorderlessGray] ]
|
||||
readonly property var disabledColorStart: [ colorStart[white], colors.baseGrayHighlight]
|
||||
readonly property var disabledColorFinish: [ colorFinish[white], colors.baseGrayShadow]
|
||||
readonly property var disabledTextColor: [ colors.lightGrayText, colors.baseGrayShadow]
|
||||
|
|
|
@ -282,7 +282,7 @@ Menu::Menu() {
|
|||
|
||||
// Navigate > Show Address Bar
|
||||
addActionToQMenuAndActionHash(navigateMenu, MenuOption::AddressBar, Qt::CTRL | Qt::Key_L,
|
||||
dialogsManager.data(), SLOT(showAddressBar()));
|
||||
dialogsManager.data(), SLOT(toggleAddressBar()));
|
||||
|
||||
// Navigate > LocationBookmarks related menus -- Note: the LocationBookmarks class adds its own submenus here.
|
||||
auto locationBookmarks = DependencyManager::get<LocationBookmarks>();
|
||||
|
|
|
@ -16,6 +16,7 @@ CheckoutProxy::CheckoutProxy(QObject* qmlObject, QObject* parent) : QmlWrapper(q
|
|||
}
|
||||
|
||||
WalletScriptingInterface::WalletScriptingInterface() {
|
||||
|
||||
}
|
||||
|
||||
void WalletScriptingInterface::refreshWalletStatus() {
|
||||
|
@ -26,4 +27,19 @@ void WalletScriptingInterface::refreshWalletStatus() {
|
|||
void WalletScriptingInterface::setWalletStatus(const uint& status) {
|
||||
_walletStatus = status;
|
||||
emit DependencyManager::get<Wallet>()->walletStatusResult(status);
|
||||
}
|
||||
|
||||
void WalletScriptingInterface::proveAvatarEntityOwnershipVerification(const QUuid& entityID) {
|
||||
QSharedPointer<ContextOverlayInterface> contextOverlayInterface = DependencyManager::get<ContextOverlayInterface>();
|
||||
EntityItemProperties entityProperties = DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(entityID,
|
||||
contextOverlayInterface->getEntityPropertyFlags());
|
||||
if (entityProperties.getClientOnly()) {
|
||||
if (!entityID.isNull() && entityProperties.getCertificateID().length() > 0) {
|
||||
contextOverlayInterface->requestOwnershipVerification(entityID);
|
||||
} else {
|
||||
qCDebug(entities) << "Failed to prove ownership of:" << entityID << "is null or not a certified item";
|
||||
}
|
||||
} else {
|
||||
qCDebug(entities) << "Failed to prove ownership of:" << entityID << "is not an avatar entity";
|
||||
}
|
||||
}
|
|
@ -21,6 +21,7 @@
|
|||
#include <OffscreenUi.h>
|
||||
#include "Application.h"
|
||||
#include "commerce/Wallet.h"
|
||||
#include "ui/overlays/ContextOverlayInterface.h"
|
||||
|
||||
class CheckoutProxy : public QmlWrapper {
|
||||
Q_OBJECT
|
||||
|
@ -39,6 +40,7 @@ public:
|
|||
|
||||
Q_INVOKABLE void refreshWalletStatus();
|
||||
Q_INVOKABLE uint getWalletStatus() { return _walletStatus; }
|
||||
Q_INVOKABLE void proveAvatarEntityOwnershipVerification(const QUuid& entityID);
|
||||
// setWalletStatus() should never be made Q_INVOKABLE. If it were,
|
||||
// scripts could cause the Wallet to incorrectly report its status.
|
||||
void setWalletStatus(const uint& status);
|
||||
|
@ -46,6 +48,8 @@ public:
|
|||
signals:
|
||||
void walletStatusChanged();
|
||||
void walletNotSetup();
|
||||
void ownershipVerificationSuccess(const QUuid& entityID);
|
||||
void ownershipVerificationFailed(const QUuid& entityID);
|
||||
|
||||
private:
|
||||
uint _walletStatus;
|
||||
|
|
|
@ -105,14 +105,14 @@ void WindowScriptingInterface::raiseMainWindow() {
|
|||
/// \param const QString& message message to display
|
||||
/// \return QScriptValue::UndefinedValue
|
||||
void WindowScriptingInterface::alert(const QString& message) {
|
||||
OffscreenUi::asyncWarning("", message);
|
||||
OffscreenUi::asyncWarning("", message, QMessageBox::Ok, QMessageBox::Ok);
|
||||
}
|
||||
|
||||
/// Display a confirmation box with the options 'Yes' and 'No'
|
||||
/// \param const QString& message message to display
|
||||
/// \return QScriptValue `true` if 'Yes' was clicked, `false` otherwise
|
||||
QScriptValue WindowScriptingInterface::confirm(const QString& message) {
|
||||
return QScriptValue((QMessageBox::Yes == OffscreenUi::question("", message, QMessageBox::Yes | QMessageBox::No)));
|
||||
return QScriptValue((QMessageBox::Yes == OffscreenUi::question("", message, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)));
|
||||
}
|
||||
|
||||
/// Display a prompt with a text box
|
||||
|
@ -354,7 +354,7 @@ QScriptValue WindowScriptingInterface::browseAssets(const QString& title, const
|
|||
return result.isEmpty() ? QScriptValue::NullValue : QScriptValue(result);
|
||||
}
|
||||
|
||||
/// Display a select asset dialog that lets the user select an asset from the Asset Server. If `directory` is an invalid
|
||||
/// Display a select asset dialog that lets the user select an asset from the Asset Server. If `directory` is an invalid
|
||||
/// directory the browser will start at the root directory.
|
||||
/// \param const QString& title title of the window
|
||||
/// \param const QString& directory directory to start the asset browser at
|
||||
|
|
|
@ -22,7 +22,7 @@ class AddressBarDialog : public OffscreenQmlDialog {
|
|||
Q_PROPERTY(bool backEnabled READ backEnabled NOTIFY backEnabledChanged)
|
||||
Q_PROPERTY(bool forwardEnabled READ forwardEnabled NOTIFY forwardEnabledChanged)
|
||||
Q_PROPERTY(bool useFeed READ useFeed WRITE setUseFeed NOTIFY useFeedChanged)
|
||||
Q_PROPERTY(QString metaverseServerUrl READ metaverseServerUrl)
|
||||
Q_PROPERTY(QString metaverseServerUrl READ metaverseServerUrl CONSTANT)
|
||||
|
||||
public:
|
||||
AddressBarDialog(QQuickItem* parent = nullptr);
|
||||
|
|
|
@ -58,7 +58,7 @@ void DialogsManager::showAddressBar() {
|
|||
hmd->openTablet();
|
||||
}
|
||||
qApp->setKeyboardFocusOverlay(hmd->getCurrentTabletScreenID());
|
||||
emit addressBarShown(true);
|
||||
setAddressBarVisible(true);
|
||||
}
|
||||
|
||||
void DialogsManager::hideAddressBar() {
|
||||
|
@ -71,7 +71,7 @@ void DialogsManager::hideAddressBar() {
|
|||
hmd->closeTablet();
|
||||
}
|
||||
qApp->setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID);
|
||||
emit addressBarShown(false);
|
||||
setAddressBarVisible(false);
|
||||
}
|
||||
|
||||
void DialogsManager::showFeed() {
|
||||
|
@ -157,6 +157,24 @@ void DialogsManager::hmdToolsClosed() {
|
|||
}
|
||||
}
|
||||
|
||||
void DialogsManager::toggleAddressBar() {
|
||||
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
||||
auto tablet = dynamic_cast<TabletProxy*>(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"));
|
||||
|
||||
const bool addressBarLoaded = tablet->isPathLoaded(TABLET_ADDRESS_DIALOG);
|
||||
|
||||
if (_addressBarVisible || addressBarLoaded) {
|
||||
hideAddressBar();
|
||||
} else {
|
||||
showAddressBar();
|
||||
}
|
||||
}
|
||||
|
||||
void DialogsManager::setAddressBarVisible(bool addressBarVisible) {
|
||||
_addressBarVisible = addressBarVisible;
|
||||
emit addressBarShown(_addressBarVisible);
|
||||
}
|
||||
|
||||
void DialogsManager::showTestingResults() {
|
||||
if (!_testingDialog) {
|
||||
_testingDialog = new TestingDialog(qApp->getWindow());
|
||||
|
|
|
@ -39,6 +39,7 @@ public:
|
|||
QPointer<OctreeStatsDialog> getOctreeStatsDialog() const { return _octreeStatsDialog; }
|
||||
QPointer<TestingDialog> getTestingDialog() const { return _testingDialog; }
|
||||
void emitAddressBarShown(bool visible) { emit addressBarShown(visible); }
|
||||
void setAddressBarVisible(bool addressBarVisible);
|
||||
|
||||
public slots:
|
||||
void showAddressBar();
|
||||
|
@ -52,6 +53,7 @@ public slots:
|
|||
void hmdTools(bool showTools);
|
||||
void showDomainConnectionDialog();
|
||||
void showTestingResults();
|
||||
void toggleAddressBar();
|
||||
|
||||
// Application Update
|
||||
void showUpdateDialog();
|
||||
|
@ -78,7 +80,7 @@ private:
|
|||
QPointer<OctreeStatsDialog> _octreeStatsDialog;
|
||||
QPointer<TestingDialog> _testingDialog;
|
||||
QPointer<DomainConnectionDialog> _domainConnectionDialog;
|
||||
bool _closeAddressBar { false };
|
||||
bool _addressBarVisible { false };
|
||||
};
|
||||
|
||||
#endif // hifi_DialogsManager_h
|
||||
|
|
|
@ -266,6 +266,93 @@ void ContextOverlayInterface::contextOverlays_hoverLeaveEntity(const EntityItemI
|
|||
}
|
||||
}
|
||||
|
||||
void ContextOverlayInterface::requestOwnershipVerification(const QUuid& entityID) {
|
||||
|
||||
setLastInspectedEntity(entityID);
|
||||
|
||||
EntityItemProperties entityProperties = _entityScriptingInterface->getEntityProperties(_lastInspectedEntity, _entityPropertyFlags);
|
||||
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
|
||||
if (entityProperties.getClientOnly()) {
|
||||
if (entityProperties.verifyStaticCertificateProperties()) {
|
||||
SharedNodePointer entityServer = nodeList->soloNodeOfType(NodeType::EntityServer);
|
||||
|
||||
if (entityServer) {
|
||||
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
||||
QNetworkRequest networkRequest;
|
||||
networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
QUrl requestURL = NetworkingConstants::METAVERSE_SERVER_URL();
|
||||
requestURL.setPath("/api/v1/commerce/proof_of_purchase_status/transfer");
|
||||
QJsonObject request;
|
||||
request["certificate_id"] = entityProperties.getCertificateID();
|
||||
networkRequest.setUrl(requestURL);
|
||||
|
||||
QNetworkReply* networkReply = NULL;
|
||||
networkReply = networkAccessManager.put(networkRequest, QJsonDocument(request).toJson());
|
||||
|
||||
connect(networkReply, &QNetworkReply::finished, [=]() {
|
||||
QJsonObject jsonObject = QJsonDocument::fromJson(networkReply->readAll()).object();
|
||||
jsonObject = jsonObject["data"].toObject();
|
||||
|
||||
if (networkReply->error() == QNetworkReply::NoError) {
|
||||
if (!jsonObject["invalid_reason"].toString().isEmpty()) {
|
||||
qCDebug(entities) << "invalid_reason not empty";
|
||||
} else if (jsonObject["transfer_status"].toArray().first().toString() == "failed") {
|
||||
qCDebug(entities) << "'transfer_status' is 'failed'";
|
||||
} else if (jsonObject["transfer_status"].toArray().first().toString() == "pending") {
|
||||
qCDebug(entities) << "'transfer_status' is 'pending'";
|
||||
} else {
|
||||
QString ownerKey = jsonObject["transfer_recipient_key"].toString();
|
||||
|
||||
QByteArray certID = entityProperties.getCertificateID().toUtf8();
|
||||
QByteArray text = DependencyManager::get<EntityTreeRenderer>()->getTree()->computeNonce(certID, ownerKey);
|
||||
QByteArray nodeToChallengeByteArray = entityProperties.getOwningAvatarID().toRfc4122();
|
||||
|
||||
int certIDByteArraySize = certID.length();
|
||||
int textByteArraySize = text.length();
|
||||
int nodeToChallengeByteArraySize = nodeToChallengeByteArray.length();
|
||||
|
||||
auto challengeOwnershipPacket = NLPacket::create(PacketType::ChallengeOwnershipRequest,
|
||||
certIDByteArraySize + textByteArraySize + nodeToChallengeByteArraySize + 3 * sizeof(int),
|
||||
true);
|
||||
challengeOwnershipPacket->writePrimitive(certIDByteArraySize);
|
||||
challengeOwnershipPacket->writePrimitive(textByteArraySize);
|
||||
challengeOwnershipPacket->writePrimitive(nodeToChallengeByteArraySize);
|
||||
challengeOwnershipPacket->write(certID);
|
||||
challengeOwnershipPacket->write(text);
|
||||
challengeOwnershipPacket->write(nodeToChallengeByteArray);
|
||||
nodeList->sendPacket(std::move(challengeOwnershipPacket), *entityServer);
|
||||
|
||||
// Kickoff a 10-second timeout timer that marks the cert if we don't get an ownership response in time
|
||||
if (thread() != QThread::currentThread()) {
|
||||
QMetaObject::invokeMethod(this, "startChallengeOwnershipTimer");
|
||||
return;
|
||||
} else {
|
||||
startChallengeOwnershipTimer();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
qCDebug(entities) << "Call to" << networkReply->url() << "failed with error" << networkReply->error() <<
|
||||
"More info:" << networkReply->readAll();
|
||||
}
|
||||
|
||||
networkReply->deleteLater();
|
||||
});
|
||||
} else {
|
||||
qCWarning(context_overlay) << "Couldn't get Entity Server!";
|
||||
}
|
||||
} else {
|
||||
auto ledger = DependencyManager::get<Ledger>();
|
||||
_challengeOwnershipTimeoutTimer.stop();
|
||||
emit ledger->updateCertificateStatus(entityProperties.getCertificateID(), (uint)(ledger->CERTIFICATE_STATUS_STATIC_VERIFICATION_FAILED));
|
||||
emit DependencyManager::get<WalletScriptingInterface>()->ownershipVerificationFailed(_lastInspectedEntity);
|
||||
qCDebug(context_overlay) << "Entity" << _lastInspectedEntity << "failed static certificate verification!";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const QString INSPECTION_CERTIFICATE_QML_PATH = "hifi/commerce/inspectionCertificate/InspectionCertificate.qml";
|
||||
void ContextOverlayInterface::openInspectionCertificate() {
|
||||
// lets open the tablet to the inspection certificate QML
|
||||
|
@ -275,87 +362,7 @@ void ContextOverlayInterface::openInspectionCertificate() {
|
|||
_hmdScriptingInterface->openTablet();
|
||||
|
||||
setLastInspectedEntity(_currentEntityWithContextOverlay);
|
||||
|
||||
EntityItemProperties entityProperties = _entityScriptingInterface->getEntityProperties(_lastInspectedEntity, _entityPropertyFlags);
|
||||
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
|
||||
if (entityProperties.getClientOnly()) {
|
||||
if (entityProperties.verifyStaticCertificateProperties()) {
|
||||
SharedNodePointer entityServer = nodeList->soloNodeOfType(NodeType::EntityServer);
|
||||
|
||||
if (entityServer) {
|
||||
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
||||
QNetworkRequest networkRequest;
|
||||
networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
QUrl requestURL = NetworkingConstants::METAVERSE_SERVER_URL();
|
||||
requestURL.setPath("/api/v1/commerce/proof_of_purchase_status/transfer");
|
||||
QJsonObject request;
|
||||
request["certificate_id"] = entityProperties.getCertificateID();
|
||||
networkRequest.setUrl(requestURL);
|
||||
|
||||
QNetworkReply* networkReply = NULL;
|
||||
networkReply = networkAccessManager.put(networkRequest, QJsonDocument(request).toJson());
|
||||
|
||||
connect(networkReply, &QNetworkReply::finished, [=]() {
|
||||
QJsonObject jsonObject = QJsonDocument::fromJson(networkReply->readAll()).object();
|
||||
jsonObject = jsonObject["data"].toObject();
|
||||
|
||||
if (networkReply->error() == QNetworkReply::NoError) {
|
||||
if (!jsonObject["invalid_reason"].toString().isEmpty()) {
|
||||
qCDebug(entities) << "invalid_reason not empty";
|
||||
} else if (jsonObject["transfer_status"].toArray().first().toString() == "failed") {
|
||||
qCDebug(entities) << "'transfer_status' is 'failed'";
|
||||
} else if (jsonObject["transfer_status"].toArray().first().toString() == "pending") {
|
||||
qCDebug(entities) << "'transfer_status' is 'pending'";
|
||||
} else {
|
||||
QString ownerKey = jsonObject["transfer_recipient_key"].toString();
|
||||
|
||||
QByteArray certID = entityProperties.getCertificateID().toUtf8();
|
||||
QByteArray text = DependencyManager::get<EntityTreeRenderer>()->getTree()->computeNonce(certID, ownerKey);
|
||||
QByteArray nodeToChallengeByteArray = entityProperties.getOwningAvatarID().toRfc4122();
|
||||
|
||||
int certIDByteArraySize = certID.length();
|
||||
int textByteArraySize = text.length();
|
||||
int nodeToChallengeByteArraySize = nodeToChallengeByteArray.length();
|
||||
|
||||
auto challengeOwnershipPacket = NLPacket::create(PacketType::ChallengeOwnershipRequest,
|
||||
certIDByteArraySize + textByteArraySize + nodeToChallengeByteArraySize + 3 * sizeof(int),
|
||||
true);
|
||||
challengeOwnershipPacket->writePrimitive(certIDByteArraySize);
|
||||
challengeOwnershipPacket->writePrimitive(textByteArraySize);
|
||||
challengeOwnershipPacket->writePrimitive(nodeToChallengeByteArraySize);
|
||||
challengeOwnershipPacket->write(certID);
|
||||
challengeOwnershipPacket->write(text);
|
||||
challengeOwnershipPacket->write(nodeToChallengeByteArray);
|
||||
nodeList->sendPacket(std::move(challengeOwnershipPacket), *entityServer);
|
||||
|
||||
// Kickoff a 10-second timeout timer that marks the cert if we don't get an ownership response in time
|
||||
if (thread() != QThread::currentThread()) {
|
||||
QMetaObject::invokeMethod(this, "startChallengeOwnershipTimer");
|
||||
return;
|
||||
} else {
|
||||
startChallengeOwnershipTimer();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
qCDebug(entities) << "Call to" << networkReply->url() << "failed with error" << networkReply->error() <<
|
||||
"More info:" << networkReply->readAll();
|
||||
}
|
||||
|
||||
networkReply->deleteLater();
|
||||
});
|
||||
} else {
|
||||
qCWarning(context_overlay) << "Couldn't get Entity Server!";
|
||||
}
|
||||
} else {
|
||||
auto ledger = DependencyManager::get<Ledger>();
|
||||
_challengeOwnershipTimeoutTimer.stop();
|
||||
emit ledger->updateCertificateStatus(entityProperties.getCertificateID(), (uint)(ledger->CERTIFICATE_STATUS_STATIC_VERIFICATION_FAILED));
|
||||
qCDebug(context_overlay) << "Entity" << _lastInspectedEntity << "failed static certificate verification!";
|
||||
}
|
||||
}
|
||||
requestOwnershipVerification(_lastInspectedEntity);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -397,6 +404,7 @@ void ContextOverlayInterface::startChallengeOwnershipTimer() {
|
|||
connect(&_challengeOwnershipTimeoutTimer, &QTimer::timeout, this, [=]() {
|
||||
qCDebug(entities) << "Ownership challenge timed out for" << _lastInspectedEntity;
|
||||
emit ledger->updateCertificateStatus(entityProperties.getCertificateID(), (uint)(ledger->CERTIFICATE_STATUS_VERIFICATION_TIMEOUT));
|
||||
emit DependencyManager::get<WalletScriptingInterface>()->ownershipVerificationFailed(_lastInspectedEntity);
|
||||
});
|
||||
|
||||
_challengeOwnershipTimeoutTimer.start(5000);
|
||||
|
@ -421,7 +429,9 @@ void ContextOverlayInterface::handleChallengeOwnershipReplyPacket(QSharedPointer
|
|||
|
||||
if (verificationSuccess) {
|
||||
emit ledger->updateCertificateStatus(certID, (uint)(ledger->CERTIFICATE_STATUS_VERIFICATION_SUCCESS));
|
||||
emit DependencyManager::get<WalletScriptingInterface>()->ownershipVerificationSuccess(_lastInspectedEntity);
|
||||
} else {
|
||||
emit ledger->updateCertificateStatus(certID, (uint)(ledger->CERTIFICATE_STATUS_OWNER_VERIFICATION_FAILED));
|
||||
emit DependencyManager::get<WalletScriptingInterface>()->ownershipVerificationFailed(_lastInspectedEntity);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "ui/overlays/Overlays.h"
|
||||
#include "scripting/HMDScriptingInterface.h"
|
||||
#include "scripting/SelectionScriptingInterface.h"
|
||||
#include "scripting/WalletScriptingInterface.h"
|
||||
|
||||
#include "EntityTree.h"
|
||||
#include "ContextOverlayLogging.h"
|
||||
|
@ -33,12 +34,13 @@
|
|||
/**jsdoc
|
||||
* @namespace ContextOverlay
|
||||
*/
|
||||
class ContextOverlayInterface : public QObject, public Dependency {
|
||||
class ContextOverlayInterface : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QUuid entityWithContextOverlay READ getCurrentEntityWithContextOverlay WRITE setCurrentEntityWithContextOverlay)
|
||||
Q_PROPERTY(bool enabled READ getEnabled WRITE setEnabled)
|
||||
Q_PROPERTY(bool isInMarketplaceInspectionMode READ getIsInMarketplaceInspectionMode WRITE setIsInMarketplaceInspectionMode)
|
||||
|
||||
QSharedPointer<EntityScriptingInterface> _entityScriptingInterface;
|
||||
EntityPropertyFlags _entityPropertyFlags;
|
||||
QSharedPointer<HMDScriptingInterface> _hmdScriptingInterface;
|
||||
|
@ -47,9 +49,7 @@ class ContextOverlayInterface : public QObject, public Dependency {
|
|||
OverlayID _contextOverlayID { UNKNOWN_OVERLAY_ID };
|
||||
std::shared_ptr<Image3DOverlay> _contextOverlay { nullptr };
|
||||
public:
|
||||
|
||||
ContextOverlayInterface();
|
||||
|
||||
Q_INVOKABLE QUuid getCurrentEntityWithContextOverlay() { return _currentEntityWithContextOverlay; }
|
||||
void setCurrentEntityWithContextOverlay(const QUuid& entityID) { _currentEntityWithContextOverlay = entityID; }
|
||||
void setLastInspectedEntity(const QUuid& entityID) { _challengeOwnershipTimeoutTimer.stop(); _lastInspectedEntity = entityID; }
|
||||
|
@ -57,6 +57,8 @@ public:
|
|||
bool getEnabled() { return _enabled; }
|
||||
bool getIsInMarketplaceInspectionMode() { return _isInMarketplaceInspectionMode; }
|
||||
void setIsInMarketplaceInspectionMode(bool mode) { _isInMarketplaceInspectionMode = mode; }
|
||||
void requestOwnershipVerification(const QUuid& entityID);
|
||||
EntityPropertyFlags getEntityPropertyFlags() { return _entityPropertyFlags; }
|
||||
|
||||
signals:
|
||||
void contextOverlayClicked(const QUuid& currentEntityWithContextOverlay);
|
||||
|
@ -80,8 +82,7 @@ private:
|
|||
enum {
|
||||
MAX_SELECTION_COUNT = 16
|
||||
};
|
||||
|
||||
bool _verboseLogging { true };
|
||||
bool _verboseLogging{ true };
|
||||
bool _enabled { true };
|
||||
EntityItemID _currentEntityWithContextOverlay{};
|
||||
EntityItemID _lastInspectedEntity{};
|
||||
|
|
|
@ -72,6 +72,15 @@ Web3DOverlay::Web3DOverlay() {
|
|||
connect(this, &Web3DOverlay::requestWebSurface, this, &Web3DOverlay::buildWebSurface);
|
||||
connect(this, &Web3DOverlay::releaseWebSurface, this, &Web3DOverlay::destroyWebSurface);
|
||||
connect(this, &Web3DOverlay::resizeWebSurface, this, &Web3DOverlay::onResizeWebSurface);
|
||||
|
||||
//need to be intialized before Tablet 1st open
|
||||
_webSurface = DependencyManager::get<OffscreenQmlSurfaceCache>()->acquire(_url);
|
||||
_webSurface->getSurfaceContext()->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("Account", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED
|
||||
_webSurface->getSurfaceContext()->setContextProperty("GlobalServices", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED
|
||||
_webSurface->getSurfaceContext()->setContextProperty("AccountServices", AccountServicesScriptingInterface::getInstance());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("AddressManager", DependencyManager::get<AddressManager>().data());
|
||||
|
||||
}
|
||||
|
||||
Web3DOverlay::Web3DOverlay(const Web3DOverlay* Web3DOverlay) :
|
||||
|
@ -192,11 +201,6 @@ void Web3DOverlay::setupQmlSurface() {
|
|||
|
||||
_webSurface->getSurfaceContext()->setContextProperty("offscreenFlags", flags);
|
||||
_webSurface->getSurfaceContext()->setContextProperty("AddressManager", DependencyManager::get<AddressManager>().data());
|
||||
|
||||
_webSurface->getSurfaceContext()->setContextProperty("Account", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED
|
||||
_webSurface->getSurfaceContext()->setContextProperty("GlobalServices", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED
|
||||
_webSurface->getSurfaceContext()->setContextProperty("AccountServices", AccountServicesScriptingInterface::getInstance());
|
||||
|
||||
// in Qt 5.10.0 there is already an "Audio" object in the QML context
|
||||
// though I failed to find it (from QtMultimedia??). So.. let it be "AudioScriptingInterface"
|
||||
_webSurface->getSurfaceContext()->setContextProperty("AudioScriptingInterface", DependencyManager::get<AudioScriptingInterface>().data());
|
||||
|
|
|
@ -192,7 +192,11 @@ void AnimSkeleton::buildSkeletonFromJoints(const std::vector<FBXJoint>& joints)
|
|||
_nonMirroredIndices.clear();
|
||||
_mirrorMap.reserve(_jointsSize);
|
||||
for (int i = 0; i < _jointsSize; i++) {
|
||||
if (_joints[i].name.endsWith("tEye")) {
|
||||
if (_joints[i].name != "Hips" && _joints[i].name != "Spine" &&
|
||||
_joints[i].name != "Spine1" && _joints[i].name != "Spine2" &&
|
||||
_joints[i].name != "Neck" && _joints[i].name != "Head" &&
|
||||
!((_joints[i].name.startsWith("Left") || _joints[i].name.startsWith("Right")) &&
|
||||
_joints[i].name != "LeftEye" && _joints[i].name != "RightEye")) {
|
||||
// HACK: we don't want to mirror some joints so we remember their indices
|
||||
// so we can restore them after a future mirror operation
|
||||
_nonMirroredIndices.push_back(i);
|
||||
|
|
|
@ -51,9 +51,9 @@ void EntityScriptServerLogClient::enableToEntityServerScriptLog(bool enable) {
|
|||
|
||||
if (_subscribed != enable) {
|
||||
if (enable) {
|
||||
emit receivedNewLogLines("====================== Subscribded to the Entity Script Server's log ======================");
|
||||
emit receivedNewLogLines("====================== Subscribed to the Entity Script Server's log ======================");
|
||||
} else {
|
||||
emit receivedNewLogLines("==================== Unsubscribded from the Entity Script Server's log ====================");
|
||||
emit receivedNewLogLines("==================== Unsubscribed from the Entity Script Server's log ====================");
|
||||
}
|
||||
}
|
||||
_subscribed = enable;
|
||||
|
|
|
@ -23,25 +23,31 @@
|
|||
#include <shared/GlobalAppProperties.h>
|
||||
#include <GLMHelpers.h>
|
||||
#include "GLLogging.h"
|
||||
#include "Config.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
|
||||
#if defined(DEBUG) || defined(USE_GLES)
|
||||
static bool enableDebugLogger = true;
|
||||
#else
|
||||
static const QString DEBUG_FLAG("HIFI_DEBUG_OPENGL");
|
||||
static bool enableDebugLogger = QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#include "Config.h"
|
||||
#include "GLHelpers.h"
|
||||
|
||||
using namespace gl;
|
||||
|
||||
|
||||
bool Context::enableDebugLogger() {
|
||||
#if defined(DEBUG) || defined(USE_GLES)
|
||||
static bool enableDebugLogger = true;
|
||||
#else
|
||||
static const QString DEBUG_FLAG("HIFI_DEBUG_OPENGL");
|
||||
static bool enableDebugLogger = QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG);
|
||||
#endif
|
||||
static std::once_flag once;
|
||||
std::call_once(once, [&] {
|
||||
// If the previous run crashed, force GL debug logging on
|
||||
if (qApp->property(hifi::properties::CRASHED).toBool()) {
|
||||
enableDebugLogger = true;
|
||||
}
|
||||
});
|
||||
return enableDebugLogger;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::atomic<size_t> Context::_totalSwapchainMemoryUsage { 0 };
|
||||
|
||||
size_t Context::getSwapchainMemoryUsage() { return _totalSwapchainMemoryUsage.load(); }
|
||||
|
@ -245,10 +251,6 @@ void Context::create() {
|
|||
// Create a temporary context to initialize glew
|
||||
static std::once_flag once;
|
||||
std::call_once(once, [&] {
|
||||
// If the previous run crashed, force GL debug logging on
|
||||
if (qApp->property(hifi::properties::CRASHED).toBool()) {
|
||||
enableDebugLogger = true;
|
||||
}
|
||||
auto hdc = GetDC(hwnd);
|
||||
setupPixelFormatSimple(hdc);
|
||||
auto glrc = wglCreateContext(hdc);
|
||||
|
@ -328,7 +330,7 @@ void Context::create() {
|
|||
contextAttribs.push_back(WGL_CONTEXT_CORE_PROFILE_BIT_ARB);
|
||||
#endif
|
||||
contextAttribs.push_back(WGL_CONTEXT_FLAGS_ARB);
|
||||
if (enableDebugLogger) {
|
||||
if (enableDebugLogger()) {
|
||||
contextAttribs.push_back(WGL_CONTEXT_DEBUG_BIT_ARB);
|
||||
} else {
|
||||
contextAttribs.push_back(0);
|
||||
|
@ -350,7 +352,7 @@ void Context::create() {
|
|||
if (!makeCurrent()) {
|
||||
throw std::runtime_error("Could not make context current");
|
||||
}
|
||||
if (enableDebugLogger) {
|
||||
if (enableDebugLogger()) {
|
||||
glDebugMessageCallback(debugMessageCallback, NULL);
|
||||
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ namespace gl {
|
|||
Context(const Context& other);
|
||||
|
||||
public:
|
||||
static bool enableDebugLogger();
|
||||
Context();
|
||||
Context(QWindow* window);
|
||||
void release();
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <QtCore/QDebug>
|
||||
#include <QtGui/QOffscreenSurface>
|
||||
#include <QtGui/QOpenGLContext>
|
||||
#include <QtGui/QOpenGLDebugLogger>
|
||||
|
||||
#include "Context.h"
|
||||
#include "GLHelpers.h"
|
||||
|
@ -68,9 +69,32 @@ bool OffscreenGLCanvas::create(QOpenGLContext* sharedContext) {
|
|||
}
|
||||
#endif
|
||||
|
||||
if (gl::Context::enableDebugLogger()) {
|
||||
_context->makeCurrent(_offscreenSurface);
|
||||
QOpenGLDebugLogger *logger = new QOpenGLDebugLogger(this);
|
||||
connect(logger, &QOpenGLDebugLogger::messageLogged, this, &OffscreenGLCanvas::onMessageLogged);
|
||||
logger->initialize();
|
||||
logger->enableMessages();
|
||||
logger->startLogging(QOpenGLDebugLogger::SynchronousLogging);
|
||||
_context->doneCurrent();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OffscreenGLCanvas::onMessageLogged(const QOpenGLDebugMessage& debugMessage) {
|
||||
auto severity = debugMessage.severity();
|
||||
switch (severity) {
|
||||
case QOpenGLDebugMessage::NotificationSeverity:
|
||||
case QOpenGLDebugMessage::LowSeverity:
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
qDebug(glLogging) << debugMessage;
|
||||
return;
|
||||
}
|
||||
|
||||
bool OffscreenGLCanvas::makeCurrent() {
|
||||
bool result = _context->makeCurrent(_offscreenSurface);
|
||||
std::call_once(_reportOnce, []{
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
class QOpenGLContext;
|
||||
class QOffscreenSurface;
|
||||
class QOpenGLDebugLogger;
|
||||
class QOpenGLDebugMessage;
|
||||
|
||||
class OffscreenGLCanvas : public QObject {
|
||||
public:
|
||||
|
@ -32,6 +32,9 @@ public:
|
|||
}
|
||||
QObject* getContextObject();
|
||||
|
||||
private slots:
|
||||
void onMessageLogged(const QOpenGLDebugMessage &debugMessage);
|
||||
|
||||
protected:
|
||||
std::once_flag _reportOnce;
|
||||
QOpenGLContext* _context{ nullptr };
|
||||
|
|
|
@ -776,7 +776,7 @@ void AddressManager::copyPath() {
|
|||
QApplication::clipboard()->setText(currentPath());
|
||||
}
|
||||
|
||||
QString AddressManager::getDomainId() const {
|
||||
QString AddressManager::getDomainID() const {
|
||||
return DependencyManager::get<NodeList>()->getDomainHandler().getUUID().toString();
|
||||
}
|
||||
|
||||
|
|
|
@ -35,9 +35,11 @@ const QString GET_PLACE = "/api/v1/places/%1";
|
|||
* The location API provides facilities related to your current location in the metaverse.
|
||||
*
|
||||
* @namespace location
|
||||
* @property {Uuid} domainId - A UUID uniquely identifying the domain you're visiting. Is {@link Uuid|Uuid.NULL} if you're not
|
||||
* @property {Uuid} domainID - A UUID uniquely identifying the domain you're visiting. Is {@link Uuid|Uuid.NULL} if you're not
|
||||
* connected to the domain.
|
||||
* <em>Read-only.</em>
|
||||
* @property {Uuid} domainId - Synonym for <code>domainId</code>. <em>Read-only.</em> <strong>Deprecated:</strong> This property
|
||||
* is deprecated and will soon be removed.
|
||||
* @property {string} hostname - The name of the domain for your current metaverse address (e.g., <code>"AvatarIsland"</code>,
|
||||
* <code>localhost</code>, or an IP address).
|
||||
* <em>Read-only.</em>
|
||||
|
@ -66,7 +68,8 @@ class AddressManager : public QObject, public Dependency {
|
|||
Q_PROPERTY(QString hostname READ getHost)
|
||||
Q_PROPERTY(QString pathname READ currentPath)
|
||||
Q_PROPERTY(QString placename READ getPlaceName)
|
||||
Q_PROPERTY(QString domainId READ getDomainId)
|
||||
Q_PROPERTY(QString domainID READ getDomainID)
|
||||
Q_PROPERTY(QString domainId READ getDomainID)
|
||||
public:
|
||||
|
||||
/**jsdoc
|
||||
|
@ -164,7 +167,7 @@ public:
|
|||
|
||||
const QUuid& getRootPlaceID() const { return _rootPlaceID; }
|
||||
const QString& getPlaceName() const { return _shareablePlaceName.isEmpty() ? _placeName : _shareablePlaceName; }
|
||||
QString getDomainId() const;
|
||||
QString getDomainID() const;
|
||||
|
||||
const QString& getHost() const { return _host; }
|
||||
|
||||
|
|
|
@ -99,7 +99,9 @@ void evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambie
|
|||
|
||||
// Diffuse from ambient
|
||||
diffuse = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lowNormalCurvature.xyz).xyz;
|
||||
specular = vec3(0.0);
|
||||
|
||||
// Scattering ambient specular is the same as non scattering for now
|
||||
// TODO: we should use the same specular answer as for direct lighting
|
||||
}
|
||||
<@endif@>
|
||||
|
||||
|
|
|
@ -543,6 +543,7 @@ void OffscreenQmlSurface::cleanup() {
|
|||
|
||||
void OffscreenQmlSurface::render() {
|
||||
#if !defined(DISABLE_QML)
|
||||
|
||||
if (nsightActive()) {
|
||||
return;
|
||||
}
|
||||
|
@ -569,14 +570,18 @@ void OffscreenQmlSurface::render() {
|
|||
|
||||
{
|
||||
// If the most recent texture was unused, we can directly recycle it
|
||||
if (_latestTextureAndFence.first) {
|
||||
offscreenTextures.releaseTexture(_latestTextureAndFence);
|
||||
_latestTextureAndFence = { 0, 0 };
|
||||
}
|
||||
|
||||
_latestTextureAndFence = { texture, glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0) };
|
||||
auto fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
// Fence will be used in another thread / context, so a flush is required
|
||||
glFlush();
|
||||
|
||||
{
|
||||
Lock lock(_latestTextureAndFenceMutex);
|
||||
if (_latestTextureAndFence.first) {
|
||||
offscreenTextures.releaseTexture(_latestTextureAndFence);
|
||||
_latestTextureAndFence = { 0, 0 };
|
||||
}
|
||||
_latestTextureAndFence = { texture, fence};
|
||||
}
|
||||
}
|
||||
|
||||
_quickWindow->resetOpenGLState();
|
||||
|
@ -588,13 +593,21 @@ void OffscreenQmlSurface::render() {
|
|||
bool OffscreenQmlSurface::fetchTexture(TextureAndFence& textureAndFence) {
|
||||
textureAndFence = { 0, 0 };
|
||||
|
||||
// Lock free early check
|
||||
if (0 == _latestTextureAndFence.first) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ensure writes to the latest texture are complete before before returning it for reading
|
||||
textureAndFence = _latestTextureAndFence;
|
||||
_latestTextureAndFence = { 0, 0 };
|
||||
{
|
||||
Lock lock(_latestTextureAndFenceMutex);
|
||||
// Double check inside the lock
|
||||
if (0 == _latestTextureAndFence.first) {
|
||||
return false;
|
||||
}
|
||||
textureAndFence = _latestTextureAndFence;
|
||||
_latestTextureAndFence = { 0, 0 };
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -813,10 +826,13 @@ void OffscreenQmlSurface::resize(const QSize& newSize_, bool forceResize) {
|
|||
|
||||
// Release hold on the textures of the old size
|
||||
if (uvec2() != _size) {
|
||||
// If the most recent texture was unused, we can directly recycle it
|
||||
if (_latestTextureAndFence.first) {
|
||||
offscreenTextures.releaseTexture(_latestTextureAndFence);
|
||||
_latestTextureAndFence = { 0, 0 };
|
||||
{
|
||||
Lock lock(_latestTextureAndFenceMutex);
|
||||
// If the most recent texture was unused, we can directly recycle it
|
||||
if (_latestTextureAndFence.first) {
|
||||
offscreenTextures.releaseTexture(_latestTextureAndFence);
|
||||
_latestTextureAndFence = { 0, 0 };
|
||||
}
|
||||
}
|
||||
offscreenTextures.releaseSize(_size);
|
||||
}
|
||||
|
|
|
@ -167,6 +167,9 @@ public slots:
|
|||
bool handlePointerEvent(const PointerEvent& event, class QTouchDevice& device, bool release = false);
|
||||
|
||||
private:
|
||||
using Mutex = std::mutex;
|
||||
using Lock = std::unique_lock<std::mutex>;
|
||||
|
||||
QQuickWindow* _quickWindow { nullptr };
|
||||
QQmlContext* _qmlContext { nullptr };
|
||||
QQuickItem* _rootItem { nullptr };
|
||||
|
@ -188,6 +191,7 @@ private:
|
|||
#endif
|
||||
|
||||
// Texture management
|
||||
Mutex _latestTextureAndFenceMutex;
|
||||
TextureAndFence _latestTextureAndFence { 0, 0 };
|
||||
|
||||
bool _render { false };
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
/node_modules
|
|
@ -1 +0,0 @@
|
|||
web: node app.js
|
|
@ -1,5 +0,0 @@
|
|||
This gameserver sets up a server with websockets that listen for messages from interface regarding when users shoot rats, and updates a real-time game board with that information. This is just a first pass, and the plan is to abstract this to work with any kind of game content creators wish to make with High Fidelity.
|
||||
|
||||
To enter the game: Run pistol.js and shoot at rats.
|
||||
For every rat you kill, you get a point.
|
||||
You're score will be displayed at https://desolate-bastion-1742.herokuapp.com/
|
|
@ -1,76 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var express = require('express');
|
||||
var http = require('http');
|
||||
var _ = require('underscore');
|
||||
var shortid = require('shortid');
|
||||
|
||||
|
||||
var app = express();
|
||||
var server = http.createServer(app);
|
||||
|
||||
var WebSocketServer = require('websocket').server;
|
||||
var wsServer = new WebSocketServer({
|
||||
httpServer: server
|
||||
});
|
||||
|
||||
var users = [];
|
||||
var connections = [];
|
||||
wsServer.on('request', function(request) {
|
||||
console.log("SOMEONE JOINED");
|
||||
var connection = request.accept(null, request.origin);
|
||||
connections.push(connection);
|
||||
connection.on('message', function(data) {
|
||||
var userData = JSON.parse(data.utf8Data);
|
||||
var user = _.find(users, function(user) {
|
||||
return user.username === userData.username;
|
||||
});
|
||||
if (user) {
|
||||
// This user already exists, so just update score
|
||||
users[users.indexOf(user)].score = userData.score;
|
||||
} else {
|
||||
users.push({
|
||||
id: shortid.generate(),
|
||||
username: userData.username,
|
||||
score: userData.score
|
||||
});
|
||||
}
|
||||
connections.forEach(function(aConnection) {
|
||||
aConnection.sendUTF(JSON.stringify({
|
||||
users: users
|
||||
}));
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/users', function(req, res) {
|
||||
res.send({
|
||||
users: users
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
/* Configuration */
|
||||
app.set('views', __dirname + '/views');
|
||||
app.use(express.static(__dirname + '/public'));
|
||||
app.set('port', (process.env.PORT || 5000));
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
app.use(express.errorHandler({
|
||||
dumpExceptions: true,
|
||||
showStack: true
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
/* Start server */
|
||||
server.listen(app.get('port'), function() {
|
||||
console.log('Express server listening on port %d in %s mode', app.get('port'), app.get('env'));
|
||||
});
|
||||
|
||||
module.exports = app;
|
|
@ -1,87 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var _ = require('underscore')
|
||||
var $ = require('jquery');
|
||||
|
||||
var UserList = React.createClass({
|
||||
render: function(){
|
||||
var sortedUsers = _.sortBy(this.props.data.users, function(users){
|
||||
//Show higher scorers at top of board
|
||||
return 1 - users.score;
|
||||
});
|
||||
var users = sortedUsers.map(function(user) {
|
||||
|
||||
return (
|
||||
<User username = {user.username} score = {user.score} key = {user.id}></User>
|
||||
)
|
||||
});
|
||||
return (
|
||||
<div>{users}</div>
|
||||
)
|
||||
}
|
||||
});
|
||||
|
||||
var GameBoard = React.createClass({
|
||||
loadDataFromServer: function(data) {
|
||||
$.ajax({
|
||||
url: this.props.url,
|
||||
dataType: 'json',
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
this.setState({data: data});
|
||||
}.bind(this),
|
||||
error: function(xhr, status, err) {
|
||||
console.error(this.props.url, status, err.toString());
|
||||
}.bind(this)
|
||||
});
|
||||
},
|
||||
getInitialState: function() {
|
||||
return {data: {users: []}};
|
||||
},
|
||||
componentDidMount: function() {
|
||||
this.loadDataFromServer();
|
||||
//set up web socket
|
||||
var path = window.location.hostname + ":" + window.location.port;
|
||||
console.log("LOCATION ", path)
|
||||
var socketClient = new WebSocket("wss://" + path);
|
||||
var self = this;
|
||||
socketClient.onopen = function() {
|
||||
console.log("CONNECTED");
|
||||
socketClient.onmessage = function(data) {
|
||||
console.log("ON MESSAGE");
|
||||
self.setState({data: JSON.parse(data.data)});
|
||||
};
|
||||
};
|
||||
|
||||
},
|
||||
render: function() {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className = "gameTitle">Kill All The Rats!</div>
|
||||
<div className = "boardHeader">
|
||||
<div className="username">PLAYER</div>
|
||||
<div className="score" > SCORE </div>
|
||||
</div>
|
||||
<UserList data ={this.state.data}/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var User = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div className = "entry">
|
||||
<div className="username"> {this.props.username} </div>
|
||||
<div className="score" > {this.props.score} </div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
})
|
||||
|
||||
React.render(
|
||||
<GameBoard url = "/users" />,
|
||||
document.getElementById('app')
|
||||
);
|
|
@ -1,15 +0,0 @@
|
|||
var gulp = require('gulp');
|
||||
var exec = require('child_process').exec;
|
||||
|
||||
gulp.task('build', function() {
|
||||
exec('npm run build', function(msg){
|
||||
console.log(msg);
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task('watch', function() {
|
||||
gulp.watch('client/*.jsx', ['build']);
|
||||
});
|
||||
|
||||
|
||||
gulp.task('default', ['build', 'watch'])
|
|
@ -1,21 +0,0 @@
|
|||
{
|
||||
"name": "KillAllTheRats",
|
||||
"version": "0.6.9",
|
||||
"scripts": {
|
||||
"build": "browserify ./client/app.jsx -t babelify --outfile ./public/js/app.js",
|
||||
"start": "node app.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"express": "^4.13.1",
|
||||
"gulp": "^3.9.0",
|
||||
"jquery": "^2.1.4",
|
||||
"react": "^0.13.3",
|
||||
"shortid": "^2.2.4",
|
||||
"underscore": "^1.8.3",
|
||||
"websocket": "^1.0.22"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babelify": "^6.1.3",
|
||||
"browserify": "^10.2.6"
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
body {
|
||||
font-family: Impact;
|
||||
background-color: #009DC0 ;
|
||||
font-size: 60px;
|
||||
}
|
||||
|
||||
.gameTitle {
|
||||
color: #D61010;
|
||||
}
|
||||
|
||||
.entry{
|
||||
width:100%;
|
||||
height:50px;
|
||||
border:1px solid #A9D1E1;
|
||||
color: white;
|
||||
margin-right:10px;
|
||||
padding: 10px;
|
||||
float:left;
|
||||
font-size: 40px;
|
||||
}
|
||||
|
||||
.boardHeader{
|
||||
width:100%;
|
||||
height:50px;
|
||||
border:5px solid #A9D1E1;
|
||||
color: white;
|
||||
margin-right:10px;
|
||||
padding: 10px;
|
||||
float:left;
|
||||
font-size: 40px;
|
||||
}
|
||||
.username{
|
||||
font-weight: bold;
|
||||
float: left;
|
||||
margin-right: 50%;
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<link rel="stylesheet" href="css/style.css">
|
||||
<title>Kill The Rats!</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script src="js/app.js"></script>
|
||||
</body>
|
||||
</html>
|
File diff suppressed because it is too large
Load diff
|
@ -1,31 +0,0 @@
|
|||
var center = Vec3.sum(MyAvatar.position, Vec3.multiply(3, Quat.getFront(Camera.getOrientation())));
|
||||
var scriptURL = Script.resolvePath("pistolScriptSpawner.js");
|
||||
var modelURL = "http://s3.amazonaws.com/hifi-public/cozza13/gun/m1911-handgun+1.fbx";
|
||||
var pistolSpawnerEntity = Entities.addEntity({
|
||||
type: 'Box',
|
||||
position: center,
|
||||
dimensions: {x: 0.38, y: 1.9, z: 3.02},
|
||||
script: scriptURL,
|
||||
visible: false,
|
||||
collisionless: true
|
||||
});
|
||||
|
||||
var pistol = Entities.addEntity({
|
||||
type: 'Model',
|
||||
modelURL: modelURL,
|
||||
position: center,
|
||||
dimensions: {x: 0.38, y: 1.9, z: 3.02},
|
||||
script: scriptURL,
|
||||
color: {red: 200, green: 0, blue: 20},
|
||||
collisionless: true
|
||||
});
|
||||
|
||||
|
||||
|
||||
function cleanup() {
|
||||
Entities.deleteEntity(pistolSpawnerEntity);
|
||||
Entities.deleteEntity(pistol);
|
||||
}
|
||||
|
||||
// Script.update.connect(update);
|
||||
Script.scriptEnding.connect(cleanup);
|
|
@ -10,7 +10,7 @@
|
|||
getControllerJointIndex, enableDispatcherModule, disableDispatcherModule,
|
||||
Messages, makeDispatcherModuleParameters, makeRunningValues, Settings, entityHasActions,
|
||||
Vec3, Overlays, flatten, Xform, getControllerWorldLocation, ensureDynamic, entityIsCloneable,
|
||||
cloneEntity, DISPATCHER_PROPERTIES, TEAR_AWAY_DISTANCE
|
||||
cloneEntity, DISPATCHER_PROPERTIES, TEAR_AWAY_DISTANCE, Uuid
|
||||
*/
|
||||
|
||||
Script.include("/~/system/libraries/Xform.js");
|
||||
|
@ -269,6 +269,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
|
|||
this.grabEntityProps = null;
|
||||
this.shouldSendStart = false;
|
||||
this.equipedWithSecondary = false;
|
||||
this.handHasBeenRightsideUp = false;
|
||||
|
||||
this.parameters = makeDispatcherModuleParameters(
|
||||
300,
|
||||
|
@ -486,15 +487,17 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
|
|||
var grabbedProperties = Entities.getEntityProperties(this.targetEntityID);
|
||||
|
||||
// if an object is "equipped" and has a predefined offset, use it.
|
||||
var offsets = getAttachPointForHotspotFromSettings(this.grabbedHotspot, this.hand);
|
||||
if (offsets) {
|
||||
this.offsetPosition = offsets[0];
|
||||
this.offsetRotation = offsets[1];
|
||||
} else {
|
||||
var handJointName = this.hand === RIGHT_HAND ? "RightHand" : "LeftHand";
|
||||
if (this.grabbedHotspot.joints[handJointName]) {
|
||||
this.offsetPosition = this.grabbedHotspot.joints[handJointName][0];
|
||||
this.offsetRotation = this.grabbedHotspot.joints[handJointName][1];
|
||||
if (this.grabbedHotspot) {
|
||||
var offsets = getAttachPointForHotspotFromSettings(this.grabbedHotspot, this.hand);
|
||||
if (offsets) {
|
||||
this.offsetPosition = offsets[0];
|
||||
this.offsetRotation = offsets[1];
|
||||
} else {
|
||||
var handJointName = this.hand === RIGHT_HAND ? "RightHand" : "LeftHand";
|
||||
if (this.grabbedHotspot.joints[handJointName]) {
|
||||
this.offsetPosition = this.grabbedHotspot.joints[handJointName][0];
|
||||
this.offsetRotation = this.grabbedHotspot.joints[handJointName][1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -549,7 +552,6 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
|
|||
// 100 ms seems to be sufficient time to force the check even occur after the object has been initialized.
|
||||
Script.setTimeout(grabEquipCheck, 100);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
this.endEquipEntity = function () {
|
||||
|
@ -624,7 +626,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
|
|||
this.grabbedHotspot = potentialEquipHotspot;
|
||||
this.targetEntityID = this.grabbedHotspot.entityID;
|
||||
this.startEquipEntity(controllerData);
|
||||
this.messageGrabEnity = false;
|
||||
this.messageGrabEntity = false;
|
||||
this.equipedWithSecondary = this.secondarySmoothedSqueezed();
|
||||
return makeRunningValues(true, [potentialEquipHotspot.entityID], []);
|
||||
} else {
|
||||
|
@ -640,6 +642,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
|
|||
this.isReady = function (controllerData, deltaTime) {
|
||||
var timestamp = Date.now();
|
||||
this.updateInputs(controllerData);
|
||||
this.handHasBeenRightsideUp = false;
|
||||
return this.checkNearbyHotspots(controllerData, deltaTime, timestamp);
|
||||
};
|
||||
|
||||
|
@ -671,7 +674,14 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
|
|||
return makeRunningValues(false, [], []);
|
||||
}
|
||||
|
||||
var dropDetected = this.dropGestureProcess(deltaTime);
|
||||
var handIsUpsideDown = this.dropGestureProcess(deltaTime);
|
||||
var dropDetected = false;
|
||||
if (this.handHasBeenRightsideUp) {
|
||||
dropDetected = handIsUpsideDown;
|
||||
}
|
||||
if (!handIsUpsideDown) {
|
||||
this.handHasBeenRightsideUp = true;
|
||||
}
|
||||
|
||||
if (this.triggerSmoothedReleased() || this.secondaryReleased()) {
|
||||
if (this.shouldSendStart) {
|
||||
|
@ -692,7 +702,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
|
|||
}
|
||||
|
||||
// highlight the grabbed hotspot when the dropGesture is detected.
|
||||
if (dropDetected) {
|
||||
if (dropDetected && this.grabbedHotspot) {
|
||||
equipHotspotBuddy.updateHotspot(this.grabbedHotspot, timestamp);
|
||||
equipHotspotBuddy.highlightHotspot(this.grabbedHotspot);
|
||||
}
|
||||
|
|
|
@ -493,7 +493,7 @@ function populateNearbyUserList(selectData, oldAudioData) {
|
|||
data.push(avatarPalDatum);
|
||||
print('PAL data:', JSON.stringify(avatarPalDatum));
|
||||
});
|
||||
getConnectionData(false, location.domainId); // Even admins don't get relationship data in requestUsernameFromID (which is still needed for admin status, which comes from domain).
|
||||
getConnectionData(false, location.domainID); // Even admins don't get relationship data in requestUsernameFromID (which is still needed for admin status, which comes from domain).
|
||||
conserveResources = Object.keys(avatarsOfInterest).length > 20;
|
||||
sendToQml({ method: 'nearbyUsers', params: data });
|
||||
if (selectData) {
|
||||
|
|
|
@ -35,4 +35,5 @@
|
|||
button.editProperties({isActive: true});
|
||||
}
|
||||
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
}());
|
||||
|
|
|
@ -337,7 +337,7 @@ function fillImageDataFromPrevious() {
|
|||
containsGif: previousAnimatedSnapPath !== "",
|
||||
processingGif: false,
|
||||
shouldUpload: false,
|
||||
canBlast: location.domainId === Settings.getValue("previousSnapshotDomainID"),
|
||||
canBlast: location.domainID === Settings.getValue("previousSnapshotDomainID"),
|
||||
isLoggedIn: isLoggedIn
|
||||
};
|
||||
imageData = [];
|
||||
|
@ -416,7 +416,7 @@ function snapshotUploaded(isError, reply) {
|
|||
}
|
||||
isUploadingPrintableStill = false;
|
||||
}
|
||||
var href, domainId;
|
||||
var href, domainID;
|
||||
function takeSnapshot() {
|
||||
tablet.emitScriptEvent(JSON.stringify({
|
||||
type: "snapshot",
|
||||
|
@ -443,11 +443,11 @@ function takeSnapshot() {
|
|||
MyAvatar.setClearOverlayWhenMoving(false);
|
||||
|
||||
// We will record snapshots based on the starting location. That could change, e.g., when recording a .gif.
|
||||
// Even the domainId could change (e.g., if the user falls into a teleporter while recording).
|
||||
// Even the domainID could change (e.g., if the user falls into a teleporter while recording).
|
||||
href = location.href;
|
||||
Settings.setValue("previousSnapshotHref", href);
|
||||
domainId = location.domainId;
|
||||
Settings.setValue("previousSnapshotDomainID", domainId);
|
||||
domainID = location.domainID;
|
||||
Settings.setValue("previousSnapshotDomainID", domainID);
|
||||
|
||||
maybeDeleteSnapshotStories();
|
||||
|
||||
|
@ -548,7 +548,7 @@ function stillSnapshotTaken(pathStillSnapshot, notify) {
|
|||
}
|
||||
HMD.openTablet();
|
||||
|
||||
isDomainOpen(domainId, function (canShare) {
|
||||
isDomainOpen(domainID, function (canShare) {
|
||||
snapshotOptions = {
|
||||
containsGif: false,
|
||||
processingGif: false,
|
||||
|
@ -594,7 +594,7 @@ function processingGifStarted(pathStillSnapshot) {
|
|||
}
|
||||
HMD.openTablet();
|
||||
|
||||
isDomainOpen(domainId, function (canShare) {
|
||||
isDomainOpen(domainID, function (canShare) {
|
||||
snapshotOptions = {
|
||||
containsGif: true,
|
||||
processingGif: true,
|
||||
|
@ -622,13 +622,13 @@ function processingGifCompleted(pathAnimatedSnapshot) {
|
|||
|
||||
Settings.setValue("previousAnimatedSnapPath", pathAnimatedSnapshot);
|
||||
|
||||
isDomainOpen(domainId, function (canShare) {
|
||||
isDomainOpen(domainID, function (canShare) {
|
||||
snapshotOptions = {
|
||||
containsGif: true,
|
||||
processingGif: false,
|
||||
canShare: canShare,
|
||||
isLoggedIn: isLoggedIn,
|
||||
canBlast: location.domainId === Settings.getValue("previousSnapshotDomainID"),
|
||||
canBlast: location.domainID === Settings.getValue("previousSnapshotDomainID"),
|
||||
};
|
||||
imageData = [{ localPath: pathAnimatedSnapshot, href: href }];
|
||||
tablet.emitScriptEvent(JSON.stringify({
|
||||
|
|
Loading…
Reference in a new issue