mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 17:49:27 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into blackProp
This commit is contained in:
commit
206bc0addb
37 changed files with 491 additions and 381 deletions
BIN
interface/resources/fonts/rawline-500.ttf
Normal file
BIN
interface/resources/fonts/rawline-500.ttf
Normal file
Binary file not shown.
|
@ -6,7 +6,7 @@ import QtQuick.Layouts 1.3
|
||||||
import TabletScriptingInterface 1.0
|
import TabletScriptingInterface 1.0
|
||||||
|
|
||||||
import "."
|
import "."
|
||||||
import stylesUit 1.0
|
import stylesUit 1.0 as HifiStylesUit
|
||||||
import "../audio" as HifiAudio
|
import "../audio" as HifiAudio
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
@ -49,44 +49,116 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
width: 150
|
id: rightContainer
|
||||||
height: 50
|
width: clockItem.width > loginItem.width ? clockItem.width + clockAmPmTextMetrics.width :
|
||||||
|
loginItem.width + clockAmPmTextMetrics.width
|
||||||
|
height: parent.height
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: 15
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: 30
|
anchors.rightMargin: 20
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.bottom: parent.bottom
|
||||||
|
|
||||||
ColumnLayout {
|
function timeChanged() {
|
||||||
anchors.fill: parent
|
var date = new Date();
|
||||||
|
clockTime.text = date.toLocaleTimeString(Qt.locale("en_US"), "h:mm ap");
|
||||||
|
var regex = /[\sa-zA-z]+/;
|
||||||
|
clockTime.text = clockTime.text.replace(regex, "");
|
||||||
|
clockAmPm.text = date.toLocaleTimeString(Qt.locale("en_US"), "ap");
|
||||||
|
}
|
||||||
|
|
||||||
RalewaySemiBold {
|
Timer {
|
||||||
text: Account.loggedIn ? qsTr("Log out") : qsTr("Log in")
|
interval: 1000; running: true; repeat: true;
|
||||||
horizontalAlignment: Text.AlignRight
|
onTriggered: rightContainer.timeChanged();
|
||||||
Layout.alignment: Qt.AlignRight
|
}
|
||||||
font.pixelSize: 20
|
|
||||||
color: "#afafaf"
|
Item {
|
||||||
|
id: clockAmPmItem
|
||||||
|
width: clockAmPmTextMetrics.width
|
||||||
|
height: clockAmPmTextMetrics.height
|
||||||
|
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.right: parent.right
|
||||||
|
TextMetrics {
|
||||||
|
id: clockAmPmTextMetrics
|
||||||
|
text: clockAmPm.text
|
||||||
|
font: clockAmPm.font
|
||||||
}
|
}
|
||||||
|
Text {
|
||||||
RalewaySemiBold {
|
anchors.left: parent.left
|
||||||
visible: Account.loggedIn
|
id: clockAmPm
|
||||||
height: Account.loggedIn ? parent.height/2 - parent.spacing/2 : 0
|
anchors.right: parent.right
|
||||||
text: Account.loggedIn ? "[" + tabletRoot.usernameShort + "]" : ""
|
font.capitalization: Font.AllUppercase
|
||||||
horizontalAlignment: Text.AlignRight
|
font.pixelSize: 12
|
||||||
Layout.alignment: Qt.AlignRight
|
font.family: "Rawline"
|
||||||
font.pixelSize: 20
|
|
||||||
color: "#afafaf"
|
color: "#afafaf"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
Item {
|
||||||
anchors.fill: parent
|
id: clockItem
|
||||||
onClicked: {
|
width: clockTimeTextMetrics.width
|
||||||
if (!Account.loggedIn) {
|
height: clockTimeTextMetrics.height
|
||||||
DialogsManager.showLoginDialog()
|
anchors {
|
||||||
} else {
|
top: parent.top
|
||||||
Account.logOut()
|
topMargin: -10
|
||||||
|
right: clockAmPmItem.left
|
||||||
|
rightMargin: 5
|
||||||
|
}
|
||||||
|
TextMetrics {
|
||||||
|
id: clockTimeTextMetrics
|
||||||
|
text: clockTime.text
|
||||||
|
font: clockTime.font
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.right: parent.right
|
||||||
|
id: clockTime
|
||||||
|
font.bold: false
|
||||||
|
font.pixelSize: 36
|
||||||
|
font.family: "Rawline"
|
||||||
|
color: "#afafaf"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: loginItem
|
||||||
|
width: loginTextMetrics.width
|
||||||
|
height: loginTextMetrics.height
|
||||||
|
anchors {
|
||||||
|
bottom: parent.bottom
|
||||||
|
bottomMargin: 10
|
||||||
|
right: clockAmPmItem.left
|
||||||
|
rightMargin: 5
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
id: loginText
|
||||||
|
anchors.right: parent.right
|
||||||
|
text: Account.loggedIn ? tabletRoot.usernameShort : qsTr("Log in")
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
Layout.alignment: Qt.AlignRight
|
||||||
|
font.pixelSize: 18
|
||||||
|
font.family: "Rawline"
|
||||||
|
color: "#afafaf"
|
||||||
|
}
|
||||||
|
TextMetrics {
|
||||||
|
id: loginTextMetrics
|
||||||
|
text: loginText.text
|
||||||
|
font: loginText.font
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: {
|
||||||
|
if (!Account.loggedIn) {
|
||||||
|
DialogsManager.showLoginDialog();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Component.onCompleted: {
|
||||||
|
rightContainer.timeChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -178,10 +178,10 @@ Rectangle {
|
||||||
|
|
||||||
function setUsername(newUsername) {
|
function setUsername(newUsername) {
|
||||||
username = newUsername;
|
username = newUsername;
|
||||||
usernameShort = newUsername.substring(0, 8);
|
usernameShort = newUsername.substring(0, 14);
|
||||||
|
|
||||||
if (newUsername.length > 8) {
|
if (newUsername.length > 14) {
|
||||||
usernameShort = usernameShort + "..."
|
usernameShort = usernameShort + "..."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
20
interface/resources/qml/styles-uit/Rawline.qml
Normal file
20
interface/resources/qml/styles-uit/Rawline.qml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
//
|
||||||
|
// Rawline.qml
|
||||||
|
//
|
||||||
|
// Created by Wayne Chen on 25 Feb 2019
|
||||||
|
// Copyright 2019 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
import QtQuick 2.7
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: root
|
||||||
|
property real size: 32
|
||||||
|
font.pixelSize: size
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
horizontalAlignment: Text.AlignLeft
|
||||||
|
font.family: "Rawline"
|
||||||
|
}
|
20
interface/resources/qml/stylesUit/Rawline.qml
Normal file
20
interface/resources/qml/stylesUit/Rawline.qml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
//
|
||||||
|
// Rawline.qml
|
||||||
|
//
|
||||||
|
// Created by Wayne Chen on 25 Feb 2019
|
||||||
|
// Copyright 2019 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
import QtQuick 2.7
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: root
|
||||||
|
property real size: 32
|
||||||
|
font.pixelSize: size
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
horizontalAlignment: Text.AlignLeft
|
||||||
|
font.family: "Rawline"
|
||||||
|
}
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* The <code>HifiAbout</code> API provides information about the version of Interface that is currently running. It also
|
* The <code>HifiAbout</code> API provides information about the version of Interface that is currently running. It also
|
||||||
* provides the ability to open a Web page in an Interface browser window.
|
* has the functionality to open a web page in an Interface browser window.
|
||||||
*
|
*
|
||||||
* @namespace HifiAbout
|
* @namespace HifiAbout
|
||||||
*
|
*
|
||||||
|
@ -30,9 +30,9 @@
|
||||||
* @property {string} qtVersion - The Qt version used in Interface that is currently running. <em>Read-only.</em>
|
* @property {string} qtVersion - The Qt version used in Interface that is currently running. <em>Read-only.</em>
|
||||||
*
|
*
|
||||||
* @example <caption>Report build information for the version of Interface currently running.</caption>
|
* @example <caption>Report build information for the version of Interface currently running.</caption>
|
||||||
* print("HiFi build date: " + HifiAbout.buildDate); // 11 Feb 2019
|
* print("HiFi build date: " + HifiAbout.buildDate); // Returns the build date of the version of Interface currently running on your machine.
|
||||||
* print("HiFi version: " + HifiAbout.buildVersion); // 0.78.0
|
* print("HiFi version: " + HifiAbout.buildVersion); // Returns the build version of Interface currently running on your machine.
|
||||||
* print("Qt version: " + HifiAbout.qtVersion); // 5.10.1
|
* print("Qt version: " + HifiAbout.qtVersion); // Returns the Qt version details of the version of Interface currently running on your machine.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class AboutUtil : public QObject {
|
class AboutUtil : public QObject {
|
||||||
|
@ -52,9 +52,9 @@ public:
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Display a Web page in an Interface browser window.
|
* Display a web page in an Interface browser window.
|
||||||
* @function HifiAbout.openUrl
|
* @function HifiAbout.openUrl
|
||||||
* @param {string} url - The URL of the Web page to display.
|
* @param {string} url - The URL of the web page you want to view in Interface.
|
||||||
*/
|
*/
|
||||||
void openUrl(const QString &url) const;
|
void openUrl(const QString &url) const;
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -1061,6 +1061,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
connect(PluginManager::getInstance().data(), &PluginManager::inputDeviceRunningChanged,
|
connect(PluginManager::getInstance().data(), &PluginManager::inputDeviceRunningChanged,
|
||||||
controllerScriptingInterface, &controller::ScriptingInterface::updateRunningInputDevices);
|
controllerScriptingInterface, &controller::ScriptingInterface::updateRunningInputDevices);
|
||||||
|
|
||||||
|
EntityTree::setEntityClicksCapturedOperator([this] {
|
||||||
|
return _controllerScriptingInterface->areEntityClicksCaptured();
|
||||||
|
});
|
||||||
|
|
||||||
_entityClipboard->createRootElement();
|
_entityClipboard->createRootElement();
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
|
@ -1075,6 +1079,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
QFontDatabase::addApplicationFont(PathUtils::resourcesPath() + "fonts/FiraSans-SemiBold.ttf");
|
QFontDatabase::addApplicationFont(PathUtils::resourcesPath() + "fonts/FiraSans-SemiBold.ttf");
|
||||||
QFontDatabase::addApplicationFont(PathUtils::resourcesPath() + "fonts/Raleway-Light.ttf");
|
QFontDatabase::addApplicationFont(PathUtils::resourcesPath() + "fonts/Raleway-Light.ttf");
|
||||||
QFontDatabase::addApplicationFont(PathUtils::resourcesPath() + "fonts/Raleway-Regular.ttf");
|
QFontDatabase::addApplicationFont(PathUtils::resourcesPath() + "fonts/Raleway-Regular.ttf");
|
||||||
|
QFontDatabase::addApplicationFont(PathUtils::resourcesPath() + "fonts/rawline-500.ttf");
|
||||||
QFontDatabase::addApplicationFont(PathUtils::resourcesPath() + "fonts/Raleway-Bold.ttf");
|
QFontDatabase::addApplicationFont(PathUtils::resourcesPath() + "fonts/Raleway-Bold.ttf");
|
||||||
QFontDatabase::addApplicationFont(PathUtils::resourcesPath() + "fonts/Raleway-SemiBold.ttf");
|
QFontDatabase::addApplicationFont(PathUtils::resourcesPath() + "fonts/Raleway-SemiBold.ttf");
|
||||||
QFontDatabase::addApplicationFont(PathUtils::resourcesPath() + "fonts/Cairo-SemiBold.ttf");
|
QFontDatabase::addApplicationFont(PathUtils::resourcesPath() + "fonts/Cairo-SemiBold.ttf");
|
||||||
|
@ -4391,7 +4396,6 @@ void Application::mouseMoveEvent(QMouseEvent* event) {
|
||||||
if (compositor.getReticleVisible() || !isHMDMode() || !compositor.getReticleOverDesktop() ||
|
if (compositor.getReticleVisible() || !isHMDMode() || !compositor.getReticleOverDesktop() ||
|
||||||
getOverlays().getOverlayAtPoint(glm::vec2(transformedPos.x(), transformedPos.y())) != UNKNOWN_ENTITY_ID) {
|
getOverlays().getOverlayAtPoint(glm::vec2(transformedPos.x(), transformedPos.y())) != UNKNOWN_ENTITY_ID) {
|
||||||
getEntities()->mouseMoveEvent(&mappedEvent);
|
getEntities()->mouseMoveEvent(&mappedEvent);
|
||||||
getOverlays().mouseMoveEvent(&mappedEvent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_controllerScriptingInterface->emitMouseMoveEvent(&mappedEvent); // send events to any registered scripts
|
_controllerScriptingInterface->emitMouseMoveEvent(&mappedEvent); // send events to any registered scripts
|
||||||
|
@ -4425,14 +4429,8 @@ void Application::mousePressEvent(QMouseEvent* event) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QMouseEvent mappedEvent(event->type(), transformedPos, event->screenPos(), event->button(), event->buttons(), event->modifiers());
|
QMouseEvent mappedEvent(event->type(), transformedPos, event->screenPos(), event->button(), event->buttons(), event->modifiers());
|
||||||
std::pair<float, QUuid> entityResult;
|
QUuid result = getEntities()->mousePressEvent(&mappedEvent);
|
||||||
if (!_controllerScriptingInterface->areEntityClicksCaptured()) {
|
setKeyboardFocusEntity(getEntities()->wantsKeyboardFocus(result) ? result : UNKNOWN_ENTITY_ID);
|
||||||
entityResult = getEntities()->mousePressEvent(&mappedEvent);
|
|
||||||
}
|
|
||||||
std::pair<float, QUuid> overlayResult = getOverlays().mousePressEvent(&mappedEvent);
|
|
||||||
|
|
||||||
QUuid focusedEntity = entityResult.first < overlayResult.first ? entityResult.second : overlayResult.second;
|
|
||||||
setKeyboardFocusEntity(getEntities()->wantsKeyboardFocus(focusedEntity) ? focusedEntity : UNKNOWN_ENTITY_ID);
|
|
||||||
|
|
||||||
_controllerScriptingInterface->emitMousePressEvent(&mappedEvent); // send events to any registered scripts
|
_controllerScriptingInterface->emitMousePressEvent(&mappedEvent); // send events to any registered scripts
|
||||||
|
|
||||||
|
@ -4471,11 +4469,7 @@ void Application::mouseDoublePressEvent(QMouseEvent* event) {
|
||||||
transformedPos,
|
transformedPos,
|
||||||
event->screenPos(), event->button(),
|
event->screenPos(), event->button(),
|
||||||
event->buttons(), event->modifiers());
|
event->buttons(), event->modifiers());
|
||||||
|
getEntities()->mouseDoublePressEvent(&mappedEvent);
|
||||||
if (!_controllerScriptingInterface->areEntityClicksCaptured()) {
|
|
||||||
getEntities()->mouseDoublePressEvent(&mappedEvent);
|
|
||||||
}
|
|
||||||
getOverlays().mouseDoublePressEvent(&mappedEvent);
|
|
||||||
|
|
||||||
// if one of our scripts have asked to capture this event, then stop processing it
|
// if one of our scripts have asked to capture this event, then stop processing it
|
||||||
if (_controllerScriptingInterface->isMouseCaptured()) {
|
if (_controllerScriptingInterface->isMouseCaptured()) {
|
||||||
|
@ -4500,7 +4494,6 @@ void Application::mouseReleaseEvent(QMouseEvent* event) {
|
||||||
event->buttons(), event->modifiers());
|
event->buttons(), event->modifiers());
|
||||||
|
|
||||||
getEntities()->mouseReleaseEvent(&mappedEvent);
|
getEntities()->mouseReleaseEvent(&mappedEvent);
|
||||||
getOverlays().mouseReleaseEvent(&mappedEvent);
|
|
||||||
|
|
||||||
_controllerScriptingInterface->emitMouseReleaseEvent(&mappedEvent); // send events to any registered scripts
|
_controllerScriptingInterface->emitMouseReleaseEvent(&mappedEvent); // send events to any registered scripts
|
||||||
|
|
||||||
|
@ -6950,7 +6943,7 @@ void Application::clearDomainOctreeDetails(bool clearAll) {
|
||||||
});
|
});
|
||||||
|
|
||||||
// reset the model renderer
|
// reset the model renderer
|
||||||
clearAll ? getEntities()->clear() : getEntities()->clearNonLocalEntities();
|
clearAll ? getEntities()->clear() : getEntities()->clearDomainAndNonOwnedEntities();
|
||||||
|
|
||||||
auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
|
auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
|
||||||
|
|
||||||
|
|
|
@ -62,8 +62,8 @@ public:
|
||||||
* <tr><th>Value</th><th>Meaning</th><th>Description</th></tr>
|
* <tr><th>Value</th><th>Meaning</th><th>Description</th></tr>
|
||||||
* </thead>
|
* </thead>
|
||||||
* <tbody>
|
* <tbody>
|
||||||
* <tr><td><code>0</code></td><td>Not logged in</td><td>The user isn't logged in.</td></tr>
|
* <tr><td><code>0</code></td><td>Not logged in</td><td>The user is not logged in.</td></tr>
|
||||||
* <tr><td><code>1</code></td><td>Not set up</td><td>The user's wallet isn't set up.</td></tr>
|
* <tr><td><code>1</code></td><td>Not set up</td><td>The user's wallet has not been set up.</td></tr>
|
||||||
* <tr><td><code>2</code></td><td>Pre-existing</td><td>There is a wallet present on the server but not one
|
* <tr><td><code>2</code></td><td>Pre-existing</td><td>There is a wallet present on the server but not one
|
||||||
* locally.</td></tr>
|
* locally.</td></tr>
|
||||||
* <tr><td><code>3</code></td><td>Conflicting</td><td>There is a wallet present on the server plus one present locally,
|
* <tr><td><code>3</code></td><td>Conflicting</td><td>There is a wallet present on the server plus one present locally,
|
||||||
|
@ -73,8 +73,8 @@ public:
|
||||||
* <tr><td><code>5</code></td><td>Ready</td><td>The wallet is ready for use.</td></tr>
|
* <tr><td><code>5</code></td><td>Ready</td><td>The wallet is ready for use.</td></tr>
|
||||||
* </tbody>
|
* </tbody>
|
||||||
* </table>
|
* </table>
|
||||||
* <p>Wallets used to be stored locally but now they're stored on the server, unless the computer once had a wallet stored
|
* <p>Wallets used to be stored locally but now they're only stored on the server. A wallet is present in both places if
|
||||||
* locally in which case the wallet may be present in both places.</p>
|
* your computer previously stored its information locally.</p>
|
||||||
* @typedef {number} WalletScriptingInterface.WalletStatus
|
* @typedef {number} WalletScriptingInterface.WalletStatus
|
||||||
*/
|
*/
|
||||||
enum WalletStatus {
|
enum WalletStatus {
|
||||||
|
|
|
@ -172,7 +172,10 @@ void LaserPointer::RenderState::update(const glm::vec3& origin, const glm::vec3&
|
||||||
properties.setVisible(true);
|
properties.setVisible(true);
|
||||||
properties.setIgnorePickIntersection(doesPathIgnorePicks());
|
properties.setIgnorePickIntersection(doesPathIgnorePicks());
|
||||||
QVector<float> widths;
|
QVector<float> widths;
|
||||||
widths.append(getLineWidth() * parentScale);
|
float width = getLineWidth() * parentScale;
|
||||||
|
widths.append(width);
|
||||||
|
widths.append(width);
|
||||||
|
properties.setStrokeWidths(widths);
|
||||||
DependencyManager::get<EntityScriptingInterface>()->editEntity(getPathID(), properties);
|
DependencyManager::get<EntityScriptingInterface>()->editEntity(getPathID(), properties);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,8 +115,8 @@ DownloadInfoResult::DownloadInfoResult() :
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Information on the assets currently being downloaded and pending download.
|
* Information on the assets currently being downloaded and pending download.
|
||||||
* @typedef {object} AccountServices.DownloadInfoResult
|
* @typedef {object} AccountServices.DownloadInfoResult
|
||||||
* @property {number[]} downloading - The percentage complete for each asset currently being downloaded.
|
* @property {number[]} downloading - The download percentage remaining of each asset currently downloading.
|
||||||
* @property {number} pending - The number of assets waiting to be download.
|
* @property {number} pending - The number of assets pending download.
|
||||||
*/
|
*/
|
||||||
QScriptValue DownloadInfoResultToScriptValue(QScriptEngine* engine, const DownloadInfoResult& result) {
|
QScriptValue DownloadInfoResultToScriptValue(QScriptEngine* engine, const DownloadInfoResult& result) {
|
||||||
QScriptValue object = engine->newObject();
|
QScriptValue object = engine->newObject();
|
||||||
|
|
|
@ -38,19 +38,19 @@ class AccountServicesScriptingInterface : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* The <code>AccountServices</code> API provides functions related to user connectivity, visibility, and asset download
|
* The <code>AccountServices</code> API provides functions that give information on user connectivity, visibility, and
|
||||||
* progress.
|
* asset download progress.
|
||||||
*
|
*
|
||||||
* @hifi-interface
|
* @hifi-interface
|
||||||
* @hifi-client-entity
|
* @hifi-client-entity
|
||||||
* @hifi-avatar
|
* @hifi-avatar
|
||||||
*
|
*
|
||||||
* @namespace AccountServices
|
* @namespace AccountServices
|
||||||
* @property {string} username - The user name if the user is logged in, otherwise <code>"Unknown user"</code>.
|
* @property {string} username - The user name of the user logged in. If there is no user logged in, it is
|
||||||
* <em>Read-only.</em>
|
* <code>"Unknown user"</code>. <em>Read-only.</em>
|
||||||
* @property {boolean} loggedIn - <code>true</code> if the user is logged in, otherwise <code>false</code>.
|
* @property {boolean} loggedIn - <code>true</code> if the user is logged in, otherwise <code>false</code>.
|
||||||
* <em>Read-only.</em>
|
* <em>Read-only.</em>
|
||||||
* @property {string} findableBy - The user's visibility to other people:<br />
|
* @property {string} findableBy - The user's visibility to other users:<br />
|
||||||
* <code>"none"</code> - user appears offline.<br />
|
* <code>"none"</code> - user appears offline.<br />
|
||||||
* <code>"friends"</code> - user is visible only to friends.<br />
|
* <code>"friends"</code> - user is visible only to friends.<br />
|
||||||
* <code>"connections"</code> - user is visible to friends and connections.<br />
|
* <code>"connections"</code> - user is visible to friends and connections.<br />
|
||||||
|
@ -74,23 +74,23 @@ public:
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Get information on the progress of downloading assets in the domain.
|
* Gets information on the download progress of assets in the domain.
|
||||||
* @function AccountServices.getDownloadInfo
|
* @function AccountServices.getDownloadInfo
|
||||||
* @returns {AccountServices.DownloadInfoResult} Information on the progress of assets download.
|
* @returns {AccountServices.DownloadInfoResult} Information on the download progress of assets.
|
||||||
*/
|
*/
|
||||||
DownloadInfoResult getDownloadInfo();
|
DownloadInfoResult getDownloadInfo();
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Cause a {@link AccountServices.downloadInfoChanged|downloadInfoChanged} signal to be triggered with information on the
|
* Triggers a {@link AccountServices.downloadInfoChanged|downloadInfoChanged} signal with information on the current
|
||||||
* current progress of the download of assets in the domain.
|
* download progress of the assets in the domain.
|
||||||
* @function AccountServices.updateDownloadInfo
|
* @function AccountServices.updateDownloadInfo
|
||||||
*/
|
*/
|
||||||
void updateDownloadInfo();
|
void updateDownloadInfo();
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Check whether the user is logged in.
|
* Checks whether the user is logged in.
|
||||||
* @function AccountServices.isLoggedIn
|
* @function AccountServices.isLoggedIn
|
||||||
* @returns {boolean} <code>true</code> if the user is logged in, <code>false</code> otherwise.
|
* @returns {boolean} <code>true</code> if the user is logged in, <code>false</code> if not.
|
||||||
* @example <caption>Report whether you are logged in.</caption>
|
* @example <caption>Report whether you are logged in.</caption>
|
||||||
* var isLoggedIn = AccountServices.isLoggedIn();
|
* var isLoggedIn = AccountServices.isLoggedIn();
|
||||||
* print("You are logged in: " + isLoggedIn); // true or false
|
* print("You are logged in: " + isLoggedIn); // true or false
|
||||||
|
@ -98,9 +98,9 @@ public slots:
|
||||||
bool isLoggedIn();
|
bool isLoggedIn();
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Prompts the user to log in (the login dialog is displayed) if they're not already logged in.
|
* The function returns the login status of the user and prompts the user to log in (with a login dialog) if they're not already logged in.
|
||||||
* @function AccountServices.checkAndSignalForAccessToken
|
* @function AccountServices.checkAndSignalForAccessToken
|
||||||
* @returns {boolean} <code>true</code> if the user is already logged in, <code>false</code> otherwise.
|
* @returns {boolean} <code>true</code> if the user is logged in, <code>false</code> if not.
|
||||||
*/
|
*/
|
||||||
bool checkAndSignalForAccessToken();
|
bool checkAndSignalForAccessToken();
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ signals:
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Triggered when the username logged in with changes, i.e., when the user logs in or out.
|
* Triggered when the username logged in with changes, i.e., when the user logs in or out.
|
||||||
* @function AccountServices.myUsernameChanged
|
* @function AccountServices.myUsernameChanged
|
||||||
* @param {string} username - The username logged in with if the user is logged in, otherwise <code>""</code>.
|
* @param {string} username - The user name of the user logged in. If there is no user logged in, it is <code>""</code>.
|
||||||
* @returns {Signal}
|
* @returns {Signal}
|
||||||
* @example <caption>Report when your username changes.</caption>
|
* @example <caption>Report when your username changes.</caption>
|
||||||
* AccountServices.myUsernameChanged.connect(function (username) {
|
* AccountServices.myUsernameChanged.connect(function (username) {
|
||||||
|
@ -150,9 +150,9 @@ signals:
|
||||||
void myUsernameChanged(const QString& username);
|
void myUsernameChanged(const QString& username);
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Triggered when the progress of the download of assets for the domain changes.
|
* Triggered when the download progress of the assets in the domain changes.
|
||||||
* @function AccountServices.downloadInfoChanged
|
* @function AccountServices.downloadInfoChanged
|
||||||
* @param {AccountServices.DownloadInfoResult} downloadInfo - Information on the progress of assets download.
|
* @param {AccountServices.DownloadInfoResult} downloadInfo - Information on the download progress of assets.
|
||||||
* @returns {Signal}
|
* @returns {Signal}
|
||||||
*/
|
*/
|
||||||
void downloadInfoChanged(DownloadInfoResult info);
|
void downloadInfoChanged(DownloadInfoResult info);
|
||||||
|
@ -186,7 +186,7 @@ signals:
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Triggered when the login status of the user changes.
|
* Triggered when the login status of the user changes.
|
||||||
* @function AccountServices.loggedInChanged
|
* @function AccountServices.loggedInChanged
|
||||||
* @param {boolean} loggedIn - <code>true</code> if the user is logged in, otherwise <code>false</code>.
|
* @param {boolean} loggedIn - <code>true</code> if the user is logged in, <code>false</code> if not.
|
||||||
* @returns {Signal}
|
* @returns {Signal}
|
||||||
* @example <caption>Report when your login status changes.</caption>
|
* @example <caption>Report when your login status changes.</caption>
|
||||||
* AccountServices.loggedInChanged.connect(function(loggedIn) {
|
* AccountServices.loggedInChanged.connect(function(loggedIn) {
|
||||||
|
|
|
@ -41,8 +41,8 @@ public:
|
||||||
*
|
*
|
||||||
* @property {WalletScriptingInterface.WalletStatus} walletStatus - The status of the user's wallet. <em>Read-only.</em>
|
* @property {WalletScriptingInterface.WalletStatus} walletStatus - The status of the user's wallet. <em>Read-only.</em>
|
||||||
* @property {boolean} limitedCommerce - <code>true</code> if Interface is running in limited commerce mode. In limited commerce
|
* @property {boolean} limitedCommerce - <code>true</code> if Interface is running in limited commerce mode. In limited commerce
|
||||||
* mode, certain Interface functionality is disabled, e.g., users can't buy non-free items from the Marketplace. The Oculus
|
* mode, certain Interface functionalities are disabled, e.g., users can't buy items that are not free from the Marketplace.
|
||||||
* Store version of Interface runs in limited commerce mode. <em>Read-only.</em>
|
* The Oculus Store version of Interface runs in limited commerce mode. <em>Read-only.</em>
|
||||||
*/
|
*/
|
||||||
class WalletScriptingInterface : public QObject, public Dependency {
|
class WalletScriptingInterface : public QObject, public Dependency {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -55,16 +55,16 @@ public:
|
||||||
WalletScriptingInterface();
|
WalletScriptingInterface();
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Check and update the user's wallet status.
|
* Checks and updates the user's wallet status.
|
||||||
* @function WalletScriptingInterface.refreshWalletStatus
|
* @function WalletScriptingInterface.refreshWalletStatus
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE void refreshWalletStatus();
|
Q_INVOKABLE void refreshWalletStatus();
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Get the current status of the user's wallet.
|
* Gets the current status of the user's wallet.
|
||||||
* @function WalletScriptingInterface.getWalletStatus
|
* @function WalletScriptingInterface.getWalletStatus
|
||||||
* @returns {WalletScriptingInterface.WalletStatus}
|
* @returns {WalletScriptingInterface.WalletStatus}
|
||||||
* @example <caption>Two ways to report your wallet status.</caption>
|
* @example <caption>Use two methods to report your wallet's status.</caption>
|
||||||
* print("Wallet status: " + WalletScriptingInterface.walletStatus); // Same value as next line.
|
* print("Wallet status: " + WalletScriptingInterface.walletStatus); // Same value as next line.
|
||||||
* print("Wallet status: " + WalletScriptingInterface.getWalletStatus());
|
* print("Wallet status: " + WalletScriptingInterface.getWalletStatus());
|
||||||
*/
|
*/
|
||||||
|
@ -74,11 +74,11 @@ public:
|
||||||
* Check that a certified avatar entity is owned by the avatar whose entity it is. The result of the check is provided via
|
* Check that a certified avatar entity is owned by the avatar whose entity it is. The result of the check is provided via
|
||||||
* the {@link WalletScriptingInterface.ownershipVerificationSuccess|ownershipVerificationSuccess} and
|
* the {@link WalletScriptingInterface.ownershipVerificationSuccess|ownershipVerificationSuccess} and
|
||||||
* {@link WalletScriptingInterface.ownershipVerificationFailed|ownershipVerificationFailed} signals.<br />
|
* {@link WalletScriptingInterface.ownershipVerificationFailed|ownershipVerificationFailed} signals.<br />
|
||||||
* <strong>Warning:</strong> Neither of these signals fire if the entity is not an avatar entity or it's not a certified
|
* <strong>Warning:</strong> Neither of these signals are triggered if the entity is not an avatar entity or is not
|
||||||
* entity.
|
* certified.
|
||||||
* @function WalletScriptingInterface.proveAvatarEntityOwnershipVerification
|
* @function WalletScriptingInterface.proveAvatarEntityOwnershipVerification
|
||||||
* @param {Uuid} entityID - The ID of the avatar entity to check.
|
* @param {Uuid} entityID - The avatar entity's ID.
|
||||||
* @example <caption>Check ownership of all nearby certified avatar entities.</caption>
|
* @example <caption>Check the ownership of all nearby certified avatar entities.</caption>
|
||||||
* // Set up response handling.
|
* // Set up response handling.
|
||||||
* function ownershipSuccess(entityID) {
|
* function ownershipSuccess(entityID) {
|
||||||
* print("Ownership test succeeded for: " + entityID);
|
* print("Ownership test succeeded for: " + entityID);
|
||||||
|
@ -118,7 +118,7 @@ public:
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Triggered when the status of the user's wallet changes.
|
* Triggered when the user's wallet status changes.
|
||||||
* @function WalletScriptingInterface.walletStatusChanged
|
* @function WalletScriptingInterface.walletStatusChanged
|
||||||
* @returns {Signal}
|
* @returns {Signal}
|
||||||
* @example <caption>Report when your wallet status changes, e.g., when you log in and out.</caption>
|
* @example <caption>Report when your wallet status changes, e.g., when you log in and out.</caption>
|
||||||
|
@ -136,7 +136,7 @@ signals:
|
||||||
void limitedCommerceChanged();
|
void limitedCommerceChanged();
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Triggered when the user rezzes a certified entity but the user's wallet is not ready and so the certified location of the
|
* Triggered when the user rezzes a certified entity but the user's wallet is not ready. So the certified location of the
|
||||||
* entity cannot be updated in the metaverse.
|
* entity cannot be updated in the metaverse.
|
||||||
* @function WalletScriptingInterface.walletNotSetup
|
* @function WalletScriptingInterface.walletNotSetup
|
||||||
* @returns {Signal}
|
* @returns {Signal}
|
||||||
|
|
|
@ -43,14 +43,6 @@ std::unordered_map<QString, QString> Overlays::_entityToOverlayTypes;
|
||||||
std::unordered_map<QString, QString> Overlays::_overlayToEntityTypes;
|
std::unordered_map<QString, QString> Overlays::_overlayToEntityTypes;
|
||||||
|
|
||||||
Overlays::Overlays() {
|
Overlays::Overlays() {
|
||||||
auto pointerManager = DependencyManager::get<PointerManager>();
|
|
||||||
connect(pointerManager.data(), &PointerManager::hoverBeginOverlay, this, &Overlays::hoverEnterPointerEvent);
|
|
||||||
connect(pointerManager.data(), &PointerManager::hoverContinueOverlay, this, &Overlays::hoverOverPointerEvent);
|
|
||||||
connect(pointerManager.data(), &PointerManager::hoverEndOverlay, this, &Overlays::hoverLeavePointerEvent);
|
|
||||||
connect(pointerManager.data(), &PointerManager::triggerBeginOverlay, this, &Overlays::mousePressPointerEvent);
|
|
||||||
connect(pointerManager.data(), &PointerManager::triggerContinueOverlay, this, &Overlays::mouseMovePointerEvent);
|
|
||||||
connect(pointerManager.data(), &PointerManager::triggerEndOverlay, this, &Overlays::mouseReleasePointerEvent);
|
|
||||||
|
|
||||||
ADD_TYPE_MAP(Box, cube);
|
ADD_TYPE_MAP(Box, cube);
|
||||||
ADD_TYPE_MAP(Sphere, sphere);
|
ADD_TYPE_MAP(Sphere, sphere);
|
||||||
_overlayToEntityTypes["rectangle3d"] = "Shape";
|
_overlayToEntityTypes["rectangle3d"] = "Shape";
|
||||||
|
@ -81,13 +73,23 @@ void Overlays::cleanupAllOverlays() {
|
||||||
|
|
||||||
void Overlays::init() {
|
void Overlays::init() {
|
||||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>().data();
|
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>().data();
|
||||||
auto pointerManager = DependencyManager::get<PointerManager>();
|
auto pointerManager = DependencyManager::get<PointerManager>().data();
|
||||||
connect(pointerManager.data(), &PointerManager::hoverBeginOverlay, entityScriptingInterface , &EntityScriptingInterface::hoverEnterEntity);
|
connect(pointerManager, &PointerManager::hoverBeginOverlay, entityScriptingInterface , &EntityScriptingInterface::hoverEnterEntity);
|
||||||
connect(pointerManager.data(), &PointerManager::hoverContinueOverlay, entityScriptingInterface, &EntityScriptingInterface::hoverOverEntity);
|
connect(pointerManager, &PointerManager::hoverContinueOverlay, entityScriptingInterface, &EntityScriptingInterface::hoverOverEntity);
|
||||||
connect(pointerManager.data(), &PointerManager::hoverEndOverlay, entityScriptingInterface, &EntityScriptingInterface::hoverLeaveEntity);
|
connect(pointerManager, &PointerManager::hoverEndOverlay, entityScriptingInterface, &EntityScriptingInterface::hoverLeaveEntity);
|
||||||
connect(pointerManager.data(), &PointerManager::triggerBeginOverlay, entityScriptingInterface, &EntityScriptingInterface::mousePressOnEntity);
|
connect(pointerManager, &PointerManager::triggerBeginOverlay, entityScriptingInterface, &EntityScriptingInterface::mousePressOnEntity);
|
||||||
connect(pointerManager.data(), &PointerManager::triggerContinueOverlay, entityScriptingInterface, &EntityScriptingInterface::mouseMoveOnEntity);
|
connect(pointerManager, &PointerManager::triggerContinueOverlay, entityScriptingInterface, &EntityScriptingInterface::mouseMoveOnEntity);
|
||||||
connect(pointerManager.data(), &PointerManager::triggerEndOverlay, entityScriptingInterface, &EntityScriptingInterface::mouseReleaseOnEntity);
|
connect(pointerManager, &PointerManager::triggerEndOverlay, entityScriptingInterface, &EntityScriptingInterface::mouseReleaseOnEntity);
|
||||||
|
|
||||||
|
connect(entityScriptingInterface, &EntityScriptingInterface::mousePressOnEntity, this, &Overlays::mousePressOnPointerEvent);
|
||||||
|
connect(entityScriptingInterface, &EntityScriptingInterface::mousePressOffEntity, this, &Overlays::mousePressOffPointerEvent);
|
||||||
|
connect(entityScriptingInterface, &EntityScriptingInterface::mouseDoublePressOnEntity, this, &Overlays::mouseDoublePressOnPointerEvent);
|
||||||
|
connect(entityScriptingInterface, &EntityScriptingInterface::mouseDoublePressOffEntity, this, &Overlays::mouseDoublePressOffPointerEvent);
|
||||||
|
connect(entityScriptingInterface, &EntityScriptingInterface::mouseReleaseOnEntity, this, &Overlays::mouseReleasePointerEvent);
|
||||||
|
connect(entityScriptingInterface, &EntityScriptingInterface::mouseMoveOnEntity, this, &Overlays::mouseMovePointerEvent);
|
||||||
|
connect(entityScriptingInterface, &EntityScriptingInterface::hoverEnterEntity , this, &Overlays::hoverEnterPointerEvent);
|
||||||
|
connect(entityScriptingInterface, &EntityScriptingInterface::hoverOverEntity, this, &Overlays::hoverOverPointerEvent);
|
||||||
|
connect(entityScriptingInterface, &EntityScriptingInterface::hoverLeaveEntity, this, &Overlays::hoverLeavePointerEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Overlays::update(float deltatime) {
|
void Overlays::update(float deltatime) {
|
||||||
|
@ -413,32 +415,13 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove
|
||||||
overlayProps["dimensions"] = vec3toVariant(ratio * dimensions);
|
overlayProps["dimensions"] = vec3toVariant(ratio * dimensions);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (add || overlayProps.contains("rotation")) {
|
if (add && !overlayProps.contains("rotation") && !overlayProps.contains("localRotation")) {
|
||||||
glm::quat rotation;
|
overlayProps["rotation"] = quatToVariant(glm::angleAxis(-(float)M_PI_2, Vectors::RIGHT));
|
||||||
{
|
} else if (overlayProps.contains("rotation")) {
|
||||||
auto iter = overlayProps.find("rotation");
|
glm::quat rotation = quatFromVariant(overlayProps["rotation"]);
|
||||||
if (iter != overlayProps.end()) {
|
|
||||||
rotation = quatFromVariant(iter.value());
|
|
||||||
} else if (!add) {
|
|
||||||
EntityPropertyFlags desiredProperties;
|
|
||||||
desiredProperties += PROP_ROTATION;
|
|
||||||
rotation = DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(id, desiredProperties).getRotation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
overlayProps["rotation"] = quatToVariant(glm::angleAxis(-(float)M_PI_2, rotation * Vectors::RIGHT) * rotation);
|
overlayProps["rotation"] = quatToVariant(glm::angleAxis(-(float)M_PI_2, rotation * Vectors::RIGHT) * rotation);
|
||||||
}
|
} else if (overlayProps.contains("localRotation")) {
|
||||||
if (add || overlayProps.contains("localRotation")) {
|
glm::quat rotation = quatFromVariant(overlayProps["localRotation"]);
|
||||||
glm::quat rotation;
|
|
||||||
{
|
|
||||||
auto iter = overlayProps.find("localRotation");
|
|
||||||
if (iter != overlayProps.end()) {
|
|
||||||
rotation = quatFromVariant(iter.value());
|
|
||||||
} else if (!add) {
|
|
||||||
EntityPropertyFlags desiredProperties;
|
|
||||||
desiredProperties += PROP_LOCAL_ROTATION;
|
|
||||||
rotation = DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(id, desiredProperties).getLocalRotation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
overlayProps["localRotation"] = quatToVariant(glm::angleAxis(-(float)M_PI_2, rotation * Vectors::RIGHT) * rotation);
|
overlayProps["localRotation"] = quatToVariant(glm::angleAxis(-(float)M_PI_2, rotation * Vectors::RIGHT) * rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1178,7 +1161,7 @@ bool Overlays::isAddedOverlay(const QUuid& id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Overlays::sendMousePressOnOverlay(const QUuid& id, const PointerEvent& event) {
|
void Overlays::sendMousePressOnOverlay(const QUuid& id, const PointerEvent& event) {
|
||||||
mousePressPointerEvent(id, event);
|
mousePressOnPointerEvent(id, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Overlays::sendMouseReleaseOnOverlay(const QUuid& id, const PointerEvent& event) {
|
void Overlays::sendMouseReleaseOnOverlay(const QUuid& id, const PointerEvent& event) {
|
||||||
|
@ -1225,57 +1208,66 @@ float Overlays::height() {
|
||||||
return offscreenUi->getWindow()->size().height();
|
return offscreenUi->getWindow()->size().height();
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t toPointerButtons(const QMouseEvent& event) {
|
void Overlays::mousePressOnPointerEvent(const QUuid& id, const PointerEvent& event) {
|
||||||
uint32_t buttons = 0;
|
auto keyboard = DependencyManager::get<Keyboard>();
|
||||||
buttons |= event.buttons().testFlag(Qt::LeftButton) ? PointerEvent::PrimaryButton : 0;
|
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed
|
||||||
buttons |= event.buttons().testFlag(Qt::RightButton) ? PointerEvent::SecondaryButton : 0;
|
if (!keyboard->getKeyIDs().contains(id)) {
|
||||||
buttons |= event.buttons().testFlag(Qt::MiddleButton) ? PointerEvent::TertiaryButton : 0;
|
auto entity = DependencyManager::get<EntityTreeRenderer>()->getEntity(id);
|
||||||
return buttons;
|
if (entity && entity->isLocalEntity()) {
|
||||||
}
|
emit mousePressOnOverlay(id, event);
|
||||||
|
|
||||||
static PointerEvent::Button toPointerButton(const QMouseEvent& event) {
|
|
||||||
switch (event.button()) {
|
|
||||||
case Qt::LeftButton:
|
|
||||||
return PointerEvent::PrimaryButton;
|
|
||||||
case Qt::RightButton:
|
|
||||||
return PointerEvent::SecondaryButton;
|
|
||||||
case Qt::MiddleButton:
|
|
||||||
return PointerEvent::TertiaryButton;
|
|
||||||
default:
|
|
||||||
return PointerEvent::NoButtons;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RayToOverlayIntersectionResult getPrevPickResult() {
|
|
||||||
RayToOverlayIntersectionResult overlayResult;
|
|
||||||
overlayResult.intersects = false;
|
|
||||||
auto pickResult = DependencyManager::get<PickManager>()->getPrevPickResultTyped<RayPickResult>(DependencyManager::get<EntityTreeRenderer>()->getMouseRayPickID());
|
|
||||||
if (pickResult) {
|
|
||||||
overlayResult.intersects = pickResult->type == IntersectionType::LOCAL_ENTITY;
|
|
||||||
if (overlayResult.intersects) {
|
|
||||||
overlayResult.intersection = pickResult->intersection;
|
|
||||||
overlayResult.distance = pickResult->distance;
|
|
||||||
overlayResult.surfaceNormal = pickResult->surfaceNormal;
|
|
||||||
overlayResult.overlayID = pickResult->objectID;
|
|
||||||
overlayResult.extraInfo = pickResult->extraInfo;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return overlayResult;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PointerEvent Overlays::calculateOverlayPointerEvent(const QUuid& id, const PickRay& ray,
|
void Overlays::mousePressOffPointerEvent() {
|
||||||
const RayToOverlayIntersectionResult& rayPickResult, QMouseEvent* event,
|
emit mousePressOffOverlay();
|
||||||
PointerEvent::EventType eventType) {
|
}
|
||||||
glm::vec2 pos2D = RayPick::projectOntoEntityXYPlane(id, rayPickResult.intersection);
|
|
||||||
return PointerEvent(eventType, PointerManager::MOUSE_POINTER_ID, pos2D, rayPickResult.intersection, rayPickResult.surfaceNormal,
|
void Overlays::mouseDoublePressOnPointerEvent(const QUuid& id, const PointerEvent& event) {
|
||||||
ray.direction, toPointerButton(*event), toPointerButtons(*event), event->modifiers());
|
auto keyboard = DependencyManager::get<Keyboard>();
|
||||||
|
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed
|
||||||
|
if (!keyboard->getKeyIDs().contains(id)) {
|
||||||
|
auto entity = DependencyManager::get<EntityTreeRenderer>()->getEntity(id);
|
||||||
|
if (entity && entity->isLocalEntity()) {
|
||||||
|
emit mouseDoublePressOnOverlay(id, event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Overlays::mouseDoublePressOffPointerEvent() {
|
||||||
|
emit mouseDoublePressOffOverlay();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Overlays::mouseReleasePointerEvent(const QUuid& id, const PointerEvent& event) {
|
||||||
|
auto keyboard = DependencyManager::get<Keyboard>();
|
||||||
|
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed
|
||||||
|
if (!keyboard->getKeyIDs().contains(id)) {
|
||||||
|
auto entity = DependencyManager::get<EntityTreeRenderer>()->getEntity(id);
|
||||||
|
if (entity && entity->isLocalEntity()) {
|
||||||
|
emit mouseReleaseOnOverlay(id, event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Overlays::mouseMovePointerEvent(const QUuid& id, const PointerEvent& event) {
|
||||||
|
auto keyboard = DependencyManager::get<Keyboard>();
|
||||||
|
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed
|
||||||
|
if (!keyboard->getKeyIDs().contains(id)) {
|
||||||
|
auto entity = DependencyManager::get<EntityTreeRenderer>()->getEntity(id);
|
||||||
|
if (entity && entity->isLocalEntity()) {
|
||||||
|
emit mouseMoveOnOverlay(id, event);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Overlays::hoverEnterPointerEvent(const QUuid& id, const PointerEvent& event) {
|
void Overlays::hoverEnterPointerEvent(const QUuid& id, const PointerEvent& event) {
|
||||||
auto keyboard = DependencyManager::get<Keyboard>();
|
auto keyboard = DependencyManager::get<Keyboard>();
|
||||||
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed
|
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed
|
||||||
if (!keyboard->getKeyIDs().contains(id)) {
|
if (!keyboard->getKeyIDs().contains(id)) {
|
||||||
emit hoverEnterOverlay(id, event);
|
auto entity = DependencyManager::get<EntityTreeRenderer>()->getEntity(id);
|
||||||
|
if (entity && entity->isLocalEntity()) {
|
||||||
|
emit hoverEnterOverlay(id, event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1283,7 +1275,10 @@ void Overlays::hoverOverPointerEvent(const QUuid& id, const PointerEvent& event)
|
||||||
auto keyboard = DependencyManager::get<Keyboard>();
|
auto keyboard = DependencyManager::get<Keyboard>();
|
||||||
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed
|
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed
|
||||||
if (!keyboard->getKeyIDs().contains(id)) {
|
if (!keyboard->getKeyIDs().contains(id)) {
|
||||||
emit hoverOverOverlay(id, event);
|
auto entity = DependencyManager::get<EntityTreeRenderer>()->getEntity(id);
|
||||||
|
if (entity && entity->isLocalEntity()) {
|
||||||
|
emit hoverOverOverlay(id, event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1291,113 +1286,10 @@ void Overlays::hoverLeavePointerEvent(const QUuid& id, const PointerEvent& event
|
||||||
auto keyboard = DependencyManager::get<Keyboard>();
|
auto keyboard = DependencyManager::get<Keyboard>();
|
||||||
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed
|
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed
|
||||||
if (!keyboard->getKeyIDs().contains(id)) {
|
if (!keyboard->getKeyIDs().contains(id)) {
|
||||||
emit hoverLeaveOverlay(id, event);
|
auto entity = DependencyManager::get<EntityTreeRenderer>()->getEntity(id);
|
||||||
}
|
if (entity && entity->isLocalEntity()) {
|
||||||
}
|
emit hoverLeaveOverlay(id, event);
|
||||||
|
|
||||||
std::pair<float, QUuid> Overlays::mousePressEvent(QMouseEvent* event) {
|
|
||||||
PerformanceTimer perfTimer("Overlays::mousePressEvent");
|
|
||||||
|
|
||||||
PickRay ray = qApp->computePickRay(event->x(), event->y());
|
|
||||||
RayToOverlayIntersectionResult rayPickResult = getPrevPickResult();
|
|
||||||
if (rayPickResult.intersects) {
|
|
||||||
_currentClickingOnOverlayID = rayPickResult.overlayID;
|
|
||||||
|
|
||||||
PointerEvent pointerEvent = calculateOverlayPointerEvent(_currentClickingOnOverlayID, ray, rayPickResult, event, PointerEvent::Press);
|
|
||||||
mousePressPointerEvent(_currentClickingOnOverlayID, pointerEvent);
|
|
||||||
return { rayPickResult.distance, rayPickResult.overlayID };
|
|
||||||
}
|
|
||||||
emit mousePressOffOverlay();
|
|
||||||
return { FLT_MAX, UNKNOWN_ENTITY_ID };
|
|
||||||
}
|
|
||||||
|
|
||||||
void Overlays::mousePressPointerEvent(const QUuid& id, const PointerEvent& event) {
|
|
||||||
auto keyboard = DependencyManager::get<Keyboard>();
|
|
||||||
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed
|
|
||||||
if (!keyboard->getKeyIDs().contains(id)) {
|
|
||||||
emit mousePressOnOverlay(id, event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Overlays::mouseDoublePressEvent(QMouseEvent* event) {
|
|
||||||
PerformanceTimer perfTimer("Overlays::mouseDoublePressEvent");
|
|
||||||
|
|
||||||
PickRay ray = qApp->computePickRay(event->x(), event->y());
|
|
||||||
RayToOverlayIntersectionResult rayPickResult = getPrevPickResult();
|
|
||||||
if (rayPickResult.intersects) {
|
|
||||||
_currentClickingOnOverlayID = rayPickResult.overlayID;
|
|
||||||
|
|
||||||
auto pointerEvent = calculateOverlayPointerEvent(_currentClickingOnOverlayID, ray, rayPickResult, event, PointerEvent::Press);
|
|
||||||
emit mouseDoublePressOnOverlay(_currentClickingOnOverlayID, pointerEvent);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
emit mouseDoublePressOffOverlay();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Overlays::mouseReleaseEvent(QMouseEvent* event) {
|
|
||||||
PerformanceTimer perfTimer("Overlays::mouseReleaseEvent");
|
|
||||||
|
|
||||||
PickRay ray = qApp->computePickRay(event->x(), event->y());
|
|
||||||
RayToOverlayIntersectionResult rayPickResult = getPrevPickResult();
|
|
||||||
if (rayPickResult.intersects) {
|
|
||||||
auto pointerEvent = calculateOverlayPointerEvent(rayPickResult.overlayID, ray, rayPickResult, event, PointerEvent::Release);
|
|
||||||
mouseReleasePointerEvent(rayPickResult.overlayID, pointerEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
_currentClickingOnOverlayID = UNKNOWN_ENTITY_ID;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Overlays::mouseReleasePointerEvent(const QUuid& id, const PointerEvent& event) {
|
|
||||||
auto keyboard = DependencyManager::get<Keyboard>();
|
|
||||||
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed
|
|
||||||
if (!keyboard->getKeyIDs().contains(id)) {
|
|
||||||
emit mouseReleaseOnOverlay(id, event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Overlays::mouseMoveEvent(QMouseEvent* event) {
|
|
||||||
PerformanceTimer perfTimer("Overlays::mouseMoveEvent");
|
|
||||||
|
|
||||||
PickRay ray = qApp->computePickRay(event->x(), event->y());
|
|
||||||
RayToOverlayIntersectionResult rayPickResult = getPrevPickResult();
|
|
||||||
if (rayPickResult.intersects) {
|
|
||||||
auto pointerEvent = calculateOverlayPointerEvent(rayPickResult.overlayID, ray, rayPickResult, event, PointerEvent::Move);
|
|
||||||
mouseMovePointerEvent(rayPickResult.overlayID, pointerEvent);
|
|
||||||
|
|
||||||
// If previously hovering over a different overlay then leave hover on that overlay.
|
|
||||||
if (_currentHoverOverOverlayID != UNKNOWN_ENTITY_ID && rayPickResult.overlayID != _currentHoverOverOverlayID) {
|
|
||||||
auto pointerEvent = calculateOverlayPointerEvent(_currentHoverOverOverlayID, ray, rayPickResult, event, PointerEvent::Move);
|
|
||||||
hoverLeavePointerEvent(_currentHoverOverOverlayID, pointerEvent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If hovering over a new overlay then enter hover on that overlay.
|
|
||||||
if (rayPickResult.overlayID != _currentHoverOverOverlayID) {
|
|
||||||
hoverEnterPointerEvent(rayPickResult.overlayID, pointerEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hover over current overlay.
|
|
||||||
hoverOverPointerEvent(rayPickResult.overlayID, pointerEvent);
|
|
||||||
|
|
||||||
_currentHoverOverOverlayID = rayPickResult.overlayID;
|
|
||||||
} else {
|
|
||||||
// If previously hovering an overlay then leave hover.
|
|
||||||
if (_currentHoverOverOverlayID != UNKNOWN_ENTITY_ID) {
|
|
||||||
auto pointerEvent = calculateOverlayPointerEvent(_currentHoverOverOverlayID, ray, rayPickResult, event, PointerEvent::Move);
|
|
||||||
hoverLeavePointerEvent(_currentHoverOverOverlayID, pointerEvent);
|
|
||||||
|
|
||||||
_currentHoverOverOverlayID = UNKNOWN_ENTITY_ID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Overlays::mouseMovePointerEvent(const QUuid& id, const PointerEvent& event) {
|
|
||||||
auto keyboard = DependencyManager::get<Keyboard>();
|
|
||||||
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed
|
|
||||||
if (!keyboard->getKeyIDs().contains(id)) {
|
|
||||||
emit mouseMoveOnOverlay(id, event);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -112,11 +112,6 @@ public:
|
||||||
const QVector<EntityItemID>& discard,
|
const QVector<EntityItemID>& discard,
|
||||||
bool visibleOnly = false, bool collidableOnly = false);
|
bool visibleOnly = false, bool collidableOnly = false);
|
||||||
|
|
||||||
std::pair<float, QUuid> mousePressEvent(QMouseEvent* event);
|
|
||||||
bool mouseDoublePressEvent(QMouseEvent* event);
|
|
||||||
bool mouseReleaseEvent(QMouseEvent* event);
|
|
||||||
bool mouseMoveEvent(QMouseEvent* event);
|
|
||||||
|
|
||||||
void cleanupAllOverlays();
|
void cleanupAllOverlays();
|
||||||
|
|
||||||
mutable QScriptEngine _scriptEngine;
|
mutable QScriptEngine _scriptEngine;
|
||||||
|
@ -719,9 +714,6 @@ private:
|
||||||
PointerEvent calculateOverlayPointerEvent(const QUuid& id, const PickRay& ray, const RayToOverlayIntersectionResult& rayPickResult,
|
PointerEvent calculateOverlayPointerEvent(const QUuid& id, const PickRay& ray, const RayToOverlayIntersectionResult& rayPickResult,
|
||||||
QMouseEvent* event, PointerEvent::EventType eventType);
|
QMouseEvent* event, PointerEvent::EventType eventType);
|
||||||
|
|
||||||
QUuid _currentClickingOnOverlayID;
|
|
||||||
QUuid _currentHoverOverOverlayID;
|
|
||||||
|
|
||||||
static QString entityToOverlayType(const QString& type);
|
static QString entityToOverlayType(const QString& type);
|
||||||
static QString overlayToEntityType(const QString& type);
|
static QString overlayToEntityType(const QString& type);
|
||||||
static std::unordered_map<QString, QString> _entityToOverlayTypes;
|
static std::unordered_map<QString, QString> _entityToOverlayTypes;
|
||||||
|
@ -732,12 +724,17 @@ private:
|
||||||
EntityItemProperties convertOverlayToEntityProperties(QVariantMap& overlayProps, std::pair<glm::quat, bool>& rotationToSave, const QString& type, bool add, const QUuid& id = QUuid());
|
EntityItemProperties convertOverlayToEntityProperties(QVariantMap& overlayProps, std::pair<glm::quat, bool>& rotationToSave, const QString& type, bool add, const QUuid& id = QUuid());
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void mousePressPointerEvent(const QUuid& id, const PointerEvent& event);
|
void mousePressOnPointerEvent(const QUuid& id, const PointerEvent& event);
|
||||||
void mouseMovePointerEvent(const QUuid& id, const PointerEvent& event);
|
void mousePressOffPointerEvent();
|
||||||
|
void mouseDoublePressOnPointerEvent(const QUuid& id, const PointerEvent& event);
|
||||||
|
void mouseDoublePressOffPointerEvent();
|
||||||
void mouseReleasePointerEvent(const QUuid& id, const PointerEvent& event);
|
void mouseReleasePointerEvent(const QUuid& id, const PointerEvent& event);
|
||||||
|
void mouseMovePointerEvent(const QUuid& id, const PointerEvent& event);
|
||||||
void hoverEnterPointerEvent(const QUuid& id, const PointerEvent& event);
|
void hoverEnterPointerEvent(const QUuid& id, const PointerEvent& event);
|
||||||
void hoverOverPointerEvent(const QUuid& id, const PointerEvent& event);
|
void hoverOverPointerEvent(const QUuid& id, const PointerEvent& event);
|
||||||
void hoverLeavePointerEvent(const QUuid& id, const PointerEvent& event);
|
void hoverLeavePointerEvent(const QUuid& id, const PointerEvent& event);
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ADD_TYPE_MAP(entity, overlay) \
|
#define ADD_TYPE_MAP(entity, overlay) \
|
||||||
|
|
|
@ -123,6 +123,42 @@ void AnimClip::copyFromNetworkAnim() {
|
||||||
const int animFrameCount = animModel.animationFrames.size();
|
const int animFrameCount = animModel.animationFrames.size();
|
||||||
_anim.resize(animFrameCount);
|
_anim.resize(animFrameCount);
|
||||||
|
|
||||||
|
// find the size scale factor for translation in the animation.
|
||||||
|
const int avatarHipsParentIndex = avatarSkeleton->getParentIndex(avatarSkeleton->nameToJointIndex("Hips"));
|
||||||
|
const int animHipsParentIndex = animSkeleton.getParentIndex(animSkeleton.nameToJointIndex("Hips"));
|
||||||
|
const AnimPose& avatarHipsAbsoluteDefaultPose = avatarSkeleton->getAbsoluteDefaultPose(avatarSkeleton->nameToJointIndex("Hips"));
|
||||||
|
const AnimPose& animHipsAbsoluteDefaultPose = animSkeleton.getAbsoluteDefaultPose(animSkeleton.nameToJointIndex("Hips"));
|
||||||
|
|
||||||
|
// the get the units and the heights for the animation and the avatar
|
||||||
|
const float avatarUnitScale = extractScale(avatarSkeleton->getGeometryOffset()).y;
|
||||||
|
const float animationUnitScale = extractScale(animModel.offset).y;
|
||||||
|
const float avatarHeightInMeters = avatarUnitScale * avatarHipsAbsoluteDefaultPose.trans().y;
|
||||||
|
const float animHeightInMeters = animationUnitScale * animHipsAbsoluteDefaultPose.trans().y;
|
||||||
|
|
||||||
|
// get the parent scales for the avatar and the animation
|
||||||
|
float avatarHipsParentScale = 1.0f;
|
||||||
|
if (avatarHipsParentIndex >= 0) {
|
||||||
|
const AnimPose& avatarHipsParentAbsoluteDefaultPose = avatarSkeleton->getAbsoluteDefaultPose(avatarHipsParentIndex);
|
||||||
|
avatarHipsParentScale = avatarHipsParentAbsoluteDefaultPose.scale().y;
|
||||||
|
}
|
||||||
|
float animHipsParentScale = 1.0f;
|
||||||
|
if (animHipsParentIndex >= 0) {
|
||||||
|
const AnimPose& animationHipsParentAbsoluteDefaultPose = animSkeleton.getAbsoluteDefaultPose(animHipsParentIndex);
|
||||||
|
animHipsParentScale = animationHipsParentAbsoluteDefaultPose.scale().y;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float EPSILON = 0.0001f;
|
||||||
|
float boneLengthScale = 1.0f;
|
||||||
|
// compute the ratios for the units, the heights in meters, and the parent scales
|
||||||
|
if ((fabsf(animHeightInMeters) > EPSILON) && (animationUnitScale > EPSILON) && (animHipsParentScale > EPSILON)) {
|
||||||
|
const float avatarToAnimationHeightRatio = avatarHeightInMeters / animHeightInMeters;
|
||||||
|
const float unitsRatio = 1.0f / (avatarUnitScale / animationUnitScale);
|
||||||
|
const float parentScaleRatio = 1.0f / (avatarHipsParentScale / animHipsParentScale);
|
||||||
|
|
||||||
|
boneLengthScale = avatarToAnimationHeightRatio * unitsRatio * parentScaleRatio;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
for (int frame = 0; frame < animFrameCount; frame++) {
|
for (int frame = 0; frame < animFrameCount; frame++) {
|
||||||
const HFMAnimationFrame& animFrame = animModel.animationFrames[frame];
|
const HFMAnimationFrame& animFrame = animModel.animationFrames[frame];
|
||||||
|
|
||||||
|
@ -162,7 +198,6 @@ void AnimClip::copyFromNetworkAnim() {
|
||||||
avatarSkeleton->convertAbsoluteRotationsToRelative(avatarRotations);
|
avatarSkeleton->convertAbsoluteRotationsToRelative(avatarRotations);
|
||||||
|
|
||||||
_anim[frame].reserve(avatarJointCount);
|
_anim[frame].reserve(avatarJointCount);
|
||||||
|
|
||||||
for (int avatarJointIndex = 0; avatarJointIndex < avatarJointCount; avatarJointIndex++) {
|
for (int avatarJointIndex = 0; avatarJointIndex < avatarJointCount; avatarJointIndex++) {
|
||||||
const AnimPose& avatarDefaultPose = avatarSkeleton->getRelativeDefaultPose(avatarJointIndex);
|
const AnimPose& avatarDefaultPose = avatarSkeleton->getRelativeDefaultPose(avatarJointIndex);
|
||||||
|
|
||||||
|
@ -177,11 +212,6 @@ void AnimClip::copyFromNetworkAnim() {
|
||||||
|
|
||||||
// retarget translation from animation to avatar
|
// retarget translation from animation to avatar
|
||||||
const glm::vec3& animZeroTrans = animModel.animationFrames[0].translations[animJointIndex];
|
const glm::vec3& animZeroTrans = animModel.animationFrames[0].translations[animJointIndex];
|
||||||
float boneLengthScale = 1.0f;
|
|
||||||
const float EPSILON = 0.0001f;
|
|
||||||
if (fabsf(glm::length(animZeroTrans)) > EPSILON) {
|
|
||||||
boneLengthScale = glm::length(avatarDefaultPose.trans()) / glm::length(animZeroTrans);
|
|
||||||
}
|
|
||||||
relativeTranslation = avatarDefaultPose.trans() + boneLengthScale * (animTrans - animZeroTrans);
|
relativeTranslation = avatarDefaultPose.trans() + boneLengthScale * (animTrans - animZeroTrans);
|
||||||
} else {
|
} else {
|
||||||
// This joint is NOT in the animation at all.
|
// This joint is NOT in the animation at all.
|
||||||
|
|
|
@ -298,10 +298,8 @@ void AnimInverseKinematics::solve(const AnimContext& context, const std::vector<
|
||||||
}
|
}
|
||||||
|
|
||||||
// harvest accumulated rotations and apply the average
|
// harvest accumulated rotations and apply the average
|
||||||
for (int i = 0; i < (int)_relativePoses.size(); ++i) {
|
// don't apply accumulators to hips, or parents of hips
|
||||||
if (i == _hipsIndex) {
|
for (int i = (_hipsIndex+1); i < (int)_relativePoses.size(); ++i) {
|
||||||
continue; // don't apply accumulators to hips
|
|
||||||
}
|
|
||||||
if (_rotationAccumulators[i].size() > 0) {
|
if (_rotationAccumulators[i].size() > 0) {
|
||||||
_relativePoses[i].rot() = _rotationAccumulators[i].getAverage();
|
_relativePoses[i].rot() = _rotationAccumulators[i].getAverage();
|
||||||
_rotationAccumulators[i].clear();
|
_rotationAccumulators[i].clear();
|
||||||
|
|
|
@ -17,6 +17,9 @@
|
||||||
#include "AnimationLogging.h"
|
#include "AnimationLogging.h"
|
||||||
|
|
||||||
AnimSkeleton::AnimSkeleton(const HFMModel& hfmModel) {
|
AnimSkeleton::AnimSkeleton(const HFMModel& hfmModel) {
|
||||||
|
|
||||||
|
_geometryOffset = hfmModel.offset;
|
||||||
|
|
||||||
// convert to std::vector of joints
|
// convert to std::vector of joints
|
||||||
std::vector<HFMJoint> joints;
|
std::vector<HFMJoint> joints;
|
||||||
joints.reserve(hfmModel.joints.size());
|
joints.reserve(hfmModel.joints.size());
|
||||||
|
|
|
@ -36,6 +36,7 @@ public:
|
||||||
const AnimPoseVec& getRelativeDefaultPoses() const { return _relativeDefaultPoses; }
|
const AnimPoseVec& getRelativeDefaultPoses() const { return _relativeDefaultPoses; }
|
||||||
const AnimPose& getAbsoluteDefaultPose(int jointIndex) const;
|
const AnimPose& getAbsoluteDefaultPose(int jointIndex) const;
|
||||||
const AnimPoseVec& getAbsoluteDefaultPoses() const { return _absoluteDefaultPoses; }
|
const AnimPoseVec& getAbsoluteDefaultPoses() const { return _absoluteDefaultPoses; }
|
||||||
|
const glm::mat4& getGeometryOffset() const { return _geometryOffset; }
|
||||||
|
|
||||||
// get pre transform which should include FBX pre potations
|
// get pre transform which should include FBX pre potations
|
||||||
const AnimPose& getPreRotationPose(int jointIndex) const;
|
const AnimPose& getPreRotationPose(int jointIndex) const;
|
||||||
|
@ -84,6 +85,7 @@ protected:
|
||||||
std::vector<int> _mirrorMap;
|
std::vector<int> _mirrorMap;
|
||||||
QHash<QString, int> _jointIndicesByName;
|
QHash<QString, int> _jointIndicesByName;
|
||||||
std::vector<std::vector<HFMCluster>> _clusterBindMatrixOriginalValues;
|
std::vector<std::vector<HFMCluster>> _clusterBindMatrixOriginalValues;
|
||||||
|
glm::mat4 _geometryOffset;
|
||||||
|
|
||||||
// no copies
|
// no copies
|
||||||
AnimSkeleton(const AnimSkeleton&) = delete;
|
AnimSkeleton(const AnimSkeleton&) = delete;
|
||||||
|
|
|
@ -73,14 +73,14 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf
|
||||||
_currentHoverOverEntityID = UNKNOWN_ENTITY_ID;
|
_currentHoverOverEntityID = UNKNOWN_ENTITY_ID;
|
||||||
_currentClickingOnEntityID = UNKNOWN_ENTITY_ID;
|
_currentClickingOnEntityID = UNKNOWN_ENTITY_ID;
|
||||||
|
|
||||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>().data();
|
||||||
auto pointerManager = DependencyManager::get<PointerManager>();
|
auto pointerManager = DependencyManager::get<PointerManager>();
|
||||||
connect(pointerManager.data(), &PointerManager::hoverBeginEntity, entityScriptingInterface.data(), &EntityScriptingInterface::hoverEnterEntity);
|
connect(pointerManager.data(), &PointerManager::hoverBeginEntity, entityScriptingInterface, &EntityScriptingInterface::hoverEnterEntity);
|
||||||
connect(pointerManager.data(), &PointerManager::hoverContinueEntity, entityScriptingInterface.data(), &EntityScriptingInterface::hoverOverEntity);
|
connect(pointerManager.data(), &PointerManager::hoverContinueEntity, entityScriptingInterface, &EntityScriptingInterface::hoverOverEntity);
|
||||||
connect(pointerManager.data(), &PointerManager::hoverEndEntity, entityScriptingInterface.data(), &EntityScriptingInterface::hoverLeaveEntity);
|
connect(pointerManager.data(), &PointerManager::hoverEndEntity, entityScriptingInterface, &EntityScriptingInterface::hoverLeaveEntity);
|
||||||
connect(pointerManager.data(), &PointerManager::triggerBeginEntity, entityScriptingInterface.data(), &EntityScriptingInterface::mousePressOnEntity);
|
connect(pointerManager.data(), &PointerManager::triggerBeginEntity, entityScriptingInterface, &EntityScriptingInterface::mousePressOnEntity);
|
||||||
connect(pointerManager.data(), &PointerManager::triggerContinueEntity, entityScriptingInterface.data(), &EntityScriptingInterface::mouseMoveOnEntity);
|
connect(pointerManager.data(), &PointerManager::triggerContinueEntity, entityScriptingInterface, &EntityScriptingInterface::mouseMoveOnEntity);
|
||||||
connect(pointerManager.data(), &PointerManager::triggerEndEntity, entityScriptingInterface.data(), &EntityScriptingInterface::mouseReleaseOnEntity);
|
connect(pointerManager.data(), &PointerManager::triggerEndEntity, entityScriptingInterface, &EntityScriptingInterface::mouseReleaseOnEntity);
|
||||||
|
|
||||||
// Forward mouse events to web entities
|
// Forward mouse events to web entities
|
||||||
auto handlePointerEvent = [&](const QUuid& entityID, const PointerEvent& event) {
|
auto handlePointerEvent = [&](const QUuid& entityID, const PointerEvent& event) {
|
||||||
|
@ -93,10 +93,10 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf
|
||||||
QMetaObject::invokeMethod(thisEntity.get(), "handlePointerEvent", Q_ARG(const PointerEvent&, event));
|
QMetaObject::invokeMethod(thisEntity.get(), "handlePointerEvent", Q_ARG(const PointerEvent&, event));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
connect(entityScriptingInterface.data(), &EntityScriptingInterface::mousePressOnEntity, this, handlePointerEvent);
|
connect(entityScriptingInterface, &EntityScriptingInterface::mousePressOnEntity, this, handlePointerEvent);
|
||||||
connect(entityScriptingInterface.data(), &EntityScriptingInterface::mouseMoveOnEntity, this, handlePointerEvent);
|
connect(entityScriptingInterface, &EntityScriptingInterface::mouseMoveOnEntity, this, handlePointerEvent);
|
||||||
connect(entityScriptingInterface.data(), &EntityScriptingInterface::mouseReleaseOnEntity, this, handlePointerEvent);
|
connect(entityScriptingInterface, &EntityScriptingInterface::mouseReleaseOnEntity, this, handlePointerEvent);
|
||||||
connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverEnterEntity, this, [&](const QUuid& entityID, const PointerEvent& event) {
|
connect(entityScriptingInterface, &EntityScriptingInterface::hoverEnterEntity, this, [&](const QUuid& entityID, const PointerEvent& event) {
|
||||||
std::shared_ptr<render::entities::WebEntityRenderer> thisEntity;
|
std::shared_ptr<render::entities::WebEntityRenderer> thisEntity;
|
||||||
auto entity = getEntity(entityID);
|
auto entity = getEntity(entityID);
|
||||||
if (entity && entity->isVisible() && entity->getType() == EntityTypes::Web) {
|
if (entity && entity->isVisible() && entity->getType() == EntityTypes::Web) {
|
||||||
|
@ -106,8 +106,8 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf
|
||||||
QMetaObject::invokeMethod(thisEntity.get(), "hoverEnterEntity", Q_ARG(const PointerEvent&, event));
|
QMetaObject::invokeMethod(thisEntity.get(), "hoverEnterEntity", Q_ARG(const PointerEvent&, event));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverOverEntity, this, handlePointerEvent);
|
connect(entityScriptingInterface, &EntityScriptingInterface::hoverOverEntity, this, handlePointerEvent);
|
||||||
connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverLeaveEntity, this, [&](const QUuid& entityID, const PointerEvent& event) {
|
connect(entityScriptingInterface, &EntityScriptingInterface::hoverLeaveEntity, this, [&](const QUuid& entityID, const PointerEvent& event) {
|
||||||
std::shared_ptr<render::entities::WebEntityRenderer> thisEntity;
|
std::shared_ptr<render::entities::WebEntityRenderer> thisEntity;
|
||||||
auto entity = getEntity(entityID);
|
auto entity = getEntity(entityID);
|
||||||
if (entity && entity->isVisible() && entity->getType() == EntityTypes::Web) {
|
if (entity && entity->isVisible() && entity->getType() == EntityTypes::Web) {
|
||||||
|
@ -196,8 +196,8 @@ void EntityTreeRenderer::resetEntitiesScriptEngine() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityTreeRenderer::stopNonLocalEntityScripts() {
|
void EntityTreeRenderer::stopDomainAndNonOwnedEntities() {
|
||||||
leaveNonLocalEntities();
|
leaveDomainAndNonOwnedEntities();
|
||||||
// unload and stop the engine
|
// unload and stop the engine
|
||||||
if (_entitiesScriptEngine) {
|
if (_entitiesScriptEngine) {
|
||||||
QList<EntityItemID> entitiesWithEntityScripts = _entitiesScriptEngine->getListOfEntityScriptIDs();
|
QList<EntityItemID> entitiesWithEntityScripts = _entitiesScriptEngine->getListOfEntityScriptIDs();
|
||||||
|
@ -206,7 +206,7 @@ void EntityTreeRenderer::stopNonLocalEntityScripts() {
|
||||||
EntityItemPointer entityItem = getTree()->findEntityByEntityItemID(entityID);
|
EntityItemPointer entityItem = getTree()->findEntityByEntityItemID(entityID);
|
||||||
|
|
||||||
if (entityItem) {
|
if (entityItem) {
|
||||||
if (!entityItem->isLocalEntity()) {
|
if (!(entityItem->isLocalEntity() || (entityItem->isAvatarEntity() && entityItem->getOwningAvatarID() == getTree()->getMyAvatarSessionUUID()))) {
|
||||||
_entitiesScriptEngine->unloadEntityScript(entityID, true);
|
_entitiesScriptEngine->unloadEntityScript(entityID, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -214,8 +214,8 @@ void EntityTreeRenderer::stopNonLocalEntityScripts() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityTreeRenderer::clearNonLocalEntities() {
|
void EntityTreeRenderer::clearDomainAndNonOwnedEntities() {
|
||||||
stopNonLocalEntityScripts();
|
stopDomainAndNonOwnedEntities();
|
||||||
|
|
||||||
std::unordered_map<EntityItemID, EntityRendererPointer> savedEntities;
|
std::unordered_map<EntityItemID, EntityRendererPointer> savedEntities;
|
||||||
// remove all entities from the scene
|
// remove all entities from the scene
|
||||||
|
@ -225,7 +225,7 @@ void EntityTreeRenderer::clearNonLocalEntities() {
|
||||||
for (const auto& entry : _entitiesInScene) {
|
for (const auto& entry : _entitiesInScene) {
|
||||||
const auto& renderer = entry.second;
|
const auto& renderer = entry.second;
|
||||||
const EntityItemPointer& entityItem = renderer->getEntity();
|
const EntityItemPointer& entityItem = renderer->getEntity();
|
||||||
if (!entityItem->isLocalEntity()) {
|
if (!(entityItem->isLocalEntity() || (entityItem->isAvatarEntity() && entityItem->getOwningAvatarID() == getTree()->getMyAvatarSessionUUID()))) {
|
||||||
renderer->removeFromScene(scene, transaction);
|
renderer->removeFromScene(scene, transaction);
|
||||||
} else {
|
} else {
|
||||||
savedEntities[entry.first] = entry.second;
|
savedEntities[entry.first] = entry.second;
|
||||||
|
@ -239,7 +239,7 @@ void EntityTreeRenderer::clearNonLocalEntities() {
|
||||||
|
|
||||||
_layeredZones.clearNonLocalLayeredZones();
|
_layeredZones.clearNonLocalLayeredZones();
|
||||||
|
|
||||||
OctreeProcessor::clearNonLocalEntities();
|
OctreeProcessor::clearDomainAndNonOwnedEntities();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityTreeRenderer::clear() {
|
void EntityTreeRenderer::clear() {
|
||||||
|
@ -655,22 +655,22 @@ bool EntityTreeRenderer::checkEnterLeaveEntities() {
|
||||||
return didUpdate;
|
return didUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityTreeRenderer::leaveNonLocalEntities() {
|
void EntityTreeRenderer::leaveDomainAndNonOwnedEntities() {
|
||||||
if (_tree && !_shuttingDown) {
|
if (_tree && !_shuttingDown) {
|
||||||
QVector<EntityItemID> currentLocalEntitiesInside;
|
QVector<EntityItemID> currentEntitiesInsideToSave;
|
||||||
foreach (const EntityItemID& entityID, _currentEntitiesInside) {
|
foreach (const EntityItemID& entityID, _currentEntitiesInside) {
|
||||||
EntityItemPointer entityItem = getTree()->findEntityByEntityItemID(entityID);
|
EntityItemPointer entityItem = getTree()->findEntityByEntityItemID(entityID);
|
||||||
if (!entityItem->isLocalEntity()) {
|
if (!(entityItem->isLocalEntity() || (entityItem->isAvatarEntity() && entityItem->getOwningAvatarID() == getTree()->getMyAvatarSessionUUID()))) {
|
||||||
emit leaveEntity(entityID);
|
emit leaveEntity(entityID);
|
||||||
if (_entitiesScriptEngine) {
|
if (_entitiesScriptEngine) {
|
||||||
_entitiesScriptEngine->callEntityScriptMethod(entityID, "leaveEntity");
|
_entitiesScriptEngine->callEntityScriptMethod(entityID, "leaveEntity");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
currentLocalEntitiesInside.push_back(entityID);
|
currentEntitiesInsideToSave.push_back(entityID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_currentEntitiesInside = currentLocalEntitiesInside;
|
_currentEntitiesInside = currentEntitiesInsideToSave;
|
||||||
forceRecheckEntities();
|
forceRecheckEntities();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -792,11 +792,11 @@ static PointerEvent::Button toPointerButton(const QMouseEvent& event) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<float, QUuid> EntityTreeRenderer::mousePressEvent(QMouseEvent* event) {
|
QUuid EntityTreeRenderer::mousePressEvent(QMouseEvent* event) {
|
||||||
// If we don't have a tree, or we're in the process of shutting down, then don't
|
// If we don't have a tree, or we're in the process of shutting down, then don't
|
||||||
// process these events.
|
// process these events.
|
||||||
if (!_tree || _shuttingDown) {
|
if (!_tree || _shuttingDown) {
|
||||||
return { FLT_MAX, UNKNOWN_ENTITY_ID };
|
return UNKNOWN_ENTITY_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
PerformanceTimer perfTimer("EntityTreeRenderer::mousePressEvent");
|
PerformanceTimer perfTimer("EntityTreeRenderer::mousePressEvent");
|
||||||
|
@ -805,11 +805,13 @@ std::pair<float, QUuid> EntityTreeRenderer::mousePressEvent(QMouseEvent* event)
|
||||||
RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID);
|
RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID);
|
||||||
EntityItemPointer entity;
|
EntityItemPointer entity;
|
||||||
if (rayPickResult.intersects && (entity = getTree()->findEntityByID(rayPickResult.entityID))) {
|
if (rayPickResult.intersects && (entity = getTree()->findEntityByID(rayPickResult.entityID))) {
|
||||||
auto properties = entity->getProperties();
|
if (!EntityTree::areEntityClicksCaptured()) {
|
||||||
QString urlString = properties.getHref();
|
auto properties = entity->getProperties();
|
||||||
QUrl url = QUrl(urlString, QUrl::StrictMode);
|
QString urlString = properties.getHref();
|
||||||
if (url.isValid() && !url.isEmpty()){
|
QUrl url = QUrl(urlString, QUrl::StrictMode);
|
||||||
DependencyManager::get<AddressManager>()->handleLookupString(urlString);
|
if (url.isValid() && !url.isEmpty()) {
|
||||||
|
DependencyManager::get<AddressManager>()->handleLookupString(urlString);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec2 pos2D = projectOntoEntityXYPlane(entity, ray, rayPickResult);
|
glm::vec2 pos2D = projectOntoEntityXYPlane(entity, ray, rayPickResult);
|
||||||
|
@ -827,10 +829,10 @@ std::pair<float, QUuid> EntityTreeRenderer::mousePressEvent(QMouseEvent* event)
|
||||||
_lastPointerEvent = pointerEvent;
|
_lastPointerEvent = pointerEvent;
|
||||||
_lastPointerEventValid = true;
|
_lastPointerEventValid = true;
|
||||||
|
|
||||||
return { rayPickResult.distance, rayPickResult.entityID };
|
return rayPickResult.entityID;
|
||||||
}
|
}
|
||||||
emit entityScriptingInterface->mousePressOffEntity();
|
emit entityScriptingInterface->mousePressOffEntity();
|
||||||
return { FLT_MAX, UNKNOWN_ENTITY_ID };
|
return UNKNOWN_ENTITY_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityTreeRenderer::mouseDoublePressEvent(QMouseEvent* event) {
|
void EntityTreeRenderer::mouseDoublePressEvent(QMouseEvent* event) {
|
||||||
|
|
|
@ -87,14 +87,14 @@ public:
|
||||||
virtual void init() override;
|
virtual void init() override;
|
||||||
|
|
||||||
/// clears the tree
|
/// clears the tree
|
||||||
virtual void clearNonLocalEntities() override;
|
virtual void clearDomainAndNonOwnedEntities() override;
|
||||||
virtual void clear() override;
|
virtual void clear() override;
|
||||||
|
|
||||||
/// reloads the entity scripts, calling unload and preload
|
/// reloads the entity scripts, calling unload and preload
|
||||||
void reloadEntityScripts();
|
void reloadEntityScripts();
|
||||||
|
|
||||||
// event handles which may generate entity related events
|
// event handles which may generate entity related events
|
||||||
std::pair<float, QUuid> mousePressEvent(QMouseEvent* event);
|
QUuid mousePressEvent(QMouseEvent* event);
|
||||||
void mouseReleaseEvent(QMouseEvent* event);
|
void mouseReleaseEvent(QMouseEvent* event);
|
||||||
void mouseDoublePressEvent(QMouseEvent* event);
|
void mouseDoublePressEvent(QMouseEvent* event);
|
||||||
void mouseMoveEvent(QMouseEvent* event);
|
void mouseMoveEvent(QMouseEvent* event);
|
||||||
|
@ -170,7 +170,7 @@ private:
|
||||||
bool findBestZoneAndMaybeContainingEntities(QVector<EntityItemID>* entitiesContainingAvatar = nullptr);
|
bool findBestZoneAndMaybeContainingEntities(QVector<EntityItemID>* entitiesContainingAvatar = nullptr);
|
||||||
|
|
||||||
bool applyLayeredZones();
|
bool applyLayeredZones();
|
||||||
void stopNonLocalEntityScripts();
|
void stopDomainAndNonOwnedEntities();
|
||||||
|
|
||||||
void checkAndCallPreload(const EntityItemID& entityID, bool reload = false, bool unloadFirst = false);
|
void checkAndCallPreload(const EntityItemID& entityID, bool reload = false, bool unloadFirst = false);
|
||||||
|
|
||||||
|
@ -179,7 +179,7 @@ private:
|
||||||
|
|
||||||
QScriptValueList createEntityArgs(const EntityItemID& entityID);
|
QScriptValueList createEntityArgs(const EntityItemID& entityID);
|
||||||
bool checkEnterLeaveEntities();
|
bool checkEnterLeaveEntities();
|
||||||
void leaveNonLocalEntities();
|
void leaveDomainAndNonOwnedEntities();
|
||||||
void leaveAllEntities();
|
void leaveAllEntities();
|
||||||
void forceRecheckEntities();
|
void forceRecheckEntities();
|
||||||
|
|
||||||
|
|
|
@ -78,13 +78,14 @@ OctreeElementPointer EntityTree::createNewElement(unsigned char* octalCode) {
|
||||||
return std::static_pointer_cast<OctreeElement>(newElement);
|
return std::static_pointer_cast<OctreeElement>(newElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityTree::eraseNonLocalEntities() {
|
void EntityTree::eraseDomainAndNonOwnedEntities() {
|
||||||
emit clearingEntities();
|
emit clearingEntities();
|
||||||
|
|
||||||
if (_simulation) {
|
if (_simulation) {
|
||||||
// local entities are not in the simulation, so we clear ALL
|
// local entities are not in the simulation, so we clear ALL
|
||||||
_simulation->clearEntities();
|
_simulation->clearEntities();
|
||||||
}
|
}
|
||||||
|
|
||||||
this->withWriteLock([&] {
|
this->withWriteLock([&] {
|
||||||
QHash<EntityItemID, EntityItemPointer> savedEntities;
|
QHash<EntityItemID, EntityItemPointer> savedEntities;
|
||||||
// NOTE: lock the Tree first, then lock the _entityMap.
|
// NOTE: lock the Tree first, then lock the _entityMap.
|
||||||
|
@ -93,10 +94,10 @@ void EntityTree::eraseNonLocalEntities() {
|
||||||
foreach(EntityItemPointer entity, _entityMap) {
|
foreach(EntityItemPointer entity, _entityMap) {
|
||||||
EntityTreeElementPointer element = entity->getElement();
|
EntityTreeElementPointer element = entity->getElement();
|
||||||
if (element) {
|
if (element) {
|
||||||
element->cleanupNonLocalEntities();
|
element->cleanupDomainAndNonOwnedEntities();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entity->isLocalEntity()) {
|
if (entity->isLocalEntity() || (entity->isAvatarEntity() && entity->getOwningAvatarID() == getMyAvatarSessionUUID())) {
|
||||||
savedEntities[entity->getEntityItemID()] = entity;
|
savedEntities[entity->getEntityItemID()] = entity;
|
||||||
} else {
|
} else {
|
||||||
int32_t spaceIndex = entity->getSpaceIndex();
|
int32_t spaceIndex = entity->getSpaceIndex();
|
||||||
|
@ -114,15 +115,16 @@ void EntityTree::eraseNonLocalEntities() {
|
||||||
|
|
||||||
{
|
{
|
||||||
QWriteLocker locker(&_needsParentFixupLock);
|
QWriteLocker locker(&_needsParentFixupLock);
|
||||||
QVector<EntityItemWeakPointer> localEntitiesNeedsParentFixup;
|
QVector<EntityItemWeakPointer> needParentFixup;
|
||||||
|
|
||||||
foreach (EntityItemWeakPointer entityItem, _needsParentFixup) {
|
foreach (EntityItemWeakPointer entityItem, _needsParentFixup) {
|
||||||
if (!entityItem.expired() && entityItem.lock()->isLocalEntity()) {
|
auto entity = entityItem.lock();
|
||||||
localEntitiesNeedsParentFixup.push_back(entityItem);
|
if (entity && (entity->isLocalEntity() || (entity->isAvatarEntity() && entity->getOwningAvatarID() == getMyAvatarSessionUUID()))) {
|
||||||
|
needParentFixup.push_back(entityItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_needsParentFixup = localEntitiesNeedsParentFixup;
|
_needsParentFixup = needParentFixup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2972,6 +2974,7 @@ QStringList EntityTree::getJointNames(const QUuid& entityID) const {
|
||||||
|
|
||||||
std::function<QObject*(const QUuid&)> EntityTree::_getEntityObjectOperator = nullptr;
|
std::function<QObject*(const QUuid&)> EntityTree::_getEntityObjectOperator = nullptr;
|
||||||
std::function<QSizeF(const QUuid&, const QString&)> EntityTree::_textSizeOperator = nullptr;
|
std::function<QSizeF(const QUuid&, const QString&)> EntityTree::_textSizeOperator = nullptr;
|
||||||
|
std::function<bool()> EntityTree::_areEntityClicksCapturedOperator = nullptr;
|
||||||
|
|
||||||
QObject* EntityTree::getEntityObject(const QUuid& id) {
|
QObject* EntityTree::getEntityObject(const QUuid& id) {
|
||||||
if (_getEntityObjectOperator) {
|
if (_getEntityObjectOperator) {
|
||||||
|
@ -2987,6 +2990,13 @@ QSizeF EntityTree::textSize(const QUuid& id, const QString& text) {
|
||||||
return QSizeF(0.0f, 0.0f);
|
return QSizeF(0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool EntityTree::areEntityClicksCaptured() {
|
||||||
|
if (_areEntityClicksCapturedOperator) {
|
||||||
|
return _areEntityClicksCapturedOperator();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void EntityTree::updateEntityQueryAACubeWorker(SpatiallyNestablePointer object, EntityEditPacketSender* packetSender,
|
void EntityTree::updateEntityQueryAACubeWorker(SpatiallyNestablePointer object, EntityEditPacketSender* packetSender,
|
||||||
MovingEntitiesOperator& moveOperator, bool force, bool tellServer) {
|
MovingEntitiesOperator& moveOperator, bool force, bool tellServer) {
|
||||||
// if the queryBox has changed, tell the entity-server
|
// if the queryBox has changed, tell the entity-server
|
||||||
|
|
|
@ -75,7 +75,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void eraseNonLocalEntities() override;
|
virtual void eraseDomainAndNonOwnedEntities() override;
|
||||||
virtual void eraseAllOctreeElements(bool createNewRoot = true) override;
|
virtual void eraseAllOctreeElements(bool createNewRoot = true) override;
|
||||||
|
|
||||||
virtual void readBitstreamToTree(const unsigned char* bitstream,
|
virtual void readBitstreamToTree(const unsigned char* bitstream,
|
||||||
|
@ -255,6 +255,7 @@ public:
|
||||||
QByteArray computeNonce(const QString& certID, const QString ownerKey);
|
QByteArray computeNonce(const QString& certID, const QString ownerKey);
|
||||||
bool verifyNonce(const QString& certID, const QString& nonce, EntityItemID& id);
|
bool verifyNonce(const QString& certID, const QString& nonce, EntityItemID& id);
|
||||||
|
|
||||||
|
QUuid getMyAvatarSessionUUID() { return _myAvatar ? _myAvatar->getSessionUUID() : QUuid(); }
|
||||||
void setMyAvatar(std::shared_ptr<AvatarData> myAvatar) { _myAvatar = myAvatar; }
|
void setMyAvatar(std::shared_ptr<AvatarData> myAvatar) { _myAvatar = myAvatar; }
|
||||||
|
|
||||||
void swapStaleProxies(std::vector<int>& proxies) { proxies.swap(_staleProxies); }
|
void swapStaleProxies(std::vector<int>& proxies) { proxies.swap(_staleProxies); }
|
||||||
|
@ -268,6 +269,9 @@ public:
|
||||||
static void setTextSizeOperator(std::function<QSizeF(const QUuid&, const QString&)> textSizeOperator) { _textSizeOperator = textSizeOperator; }
|
static void setTextSizeOperator(std::function<QSizeF(const QUuid&, const QString&)> textSizeOperator) { _textSizeOperator = textSizeOperator; }
|
||||||
static QSizeF textSize(const QUuid& id, const QString& text);
|
static QSizeF textSize(const QUuid& id, const QString& text);
|
||||||
|
|
||||||
|
static void setEntityClicksCapturedOperator(std::function<bool()> areEntityClicksCapturedOperator) { _areEntityClicksCapturedOperator = areEntityClicksCapturedOperator; }
|
||||||
|
static bool areEntityClicksCaptured();
|
||||||
|
|
||||||
std::map<QString, QString> getNamedPaths() const { return _namedPaths; }
|
std::map<QString, QString> getNamedPaths() const { return _namedPaths; }
|
||||||
|
|
||||||
void updateEntityQueryAACube(SpatiallyNestablePointer object, EntityEditPacketSender* packetSender,
|
void updateEntityQueryAACube(SpatiallyNestablePointer object, EntityEditPacketSender* packetSender,
|
||||||
|
@ -378,6 +382,7 @@ private:
|
||||||
|
|
||||||
static std::function<QObject*(const QUuid&)> _getEntityObjectOperator;
|
static std::function<QObject*(const QUuid&)> _getEntityObjectOperator;
|
||||||
static std::function<QSizeF(const QUuid&, const QString&)> _textSizeOperator;
|
static std::function<QSizeF(const QUuid&, const QString&)> _textSizeOperator;
|
||||||
|
static std::function<bool()> _areEntityClicksCapturedOperator;
|
||||||
|
|
||||||
std::vector<int32_t> _staleProxies;
|
std::vector<int32_t> _staleProxies;
|
||||||
|
|
||||||
|
|
|
@ -697,11 +697,11 @@ EntityItemPointer EntityTreeElement::getEntityWithEntityItemID(const EntityItemI
|
||||||
return foundEntity;
|
return foundEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityTreeElement::cleanupNonLocalEntities() {
|
void EntityTreeElement::cleanupDomainAndNonOwnedEntities() {
|
||||||
withWriteLock([&] {
|
withWriteLock([&] {
|
||||||
EntityItems savedEntities;
|
EntityItems savedEntities;
|
||||||
foreach(EntityItemPointer entity, _entityItems) {
|
foreach(EntityItemPointer entity, _entityItems) {
|
||||||
if (!entity->isLocalEntity()) {
|
if (!(entity->isLocalEntity() || (entity->isAvatarEntity() && entity->getOwningAvatarID() == getTree()->getMyAvatarSessionUUID()))) {
|
||||||
entity->preDelete();
|
entity->preDelete();
|
||||||
entity->_element = NULL;
|
entity->_element = NULL;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -190,7 +190,7 @@ public:
|
||||||
EntityItemPointer getEntityWithEntityItemID(const EntityItemID& id) const;
|
EntityItemPointer getEntityWithEntityItemID(const EntityItemID& id) const;
|
||||||
void getEntitiesInside(const AACube& box, QVector<EntityItemPointer>& foundEntities);
|
void getEntitiesInside(const AACube& box, QVector<EntityItemPointer>& foundEntities);
|
||||||
|
|
||||||
void cleanupNonLocalEntities();
|
void cleanupDomainAndNonOwnedEntities();
|
||||||
void cleanupEntities(); /// called by EntityTree on cleanup this will free all entities
|
void cleanupEntities(); /// called by EntityTree on cleanup this will free all entities
|
||||||
bool removeEntityItem(EntityItemPointer entity, bool deletion = false);
|
bool removeEntityItem(EntityItemPointer entity, bool deletion = false);
|
||||||
|
|
||||||
|
|
|
@ -164,7 +164,7 @@ protected:
|
||||||
int _lastKnownCurrentFrame{-1};
|
int _lastKnownCurrentFrame{-1};
|
||||||
|
|
||||||
glm::u8vec3 _color;
|
glm::u8vec3 _color;
|
||||||
glm::vec3 _modelScale;
|
glm::vec3 _modelScale { 1.0f };
|
||||||
QString _modelURL;
|
QString _modelURL;
|
||||||
bool _relayParentJoints;
|
bool _relayParentJoints;
|
||||||
bool _groupCulled { false };
|
bool _groupCulled { false };
|
||||||
|
|
|
@ -167,7 +167,6 @@ glm::mat4 getGlobalTransform(const QMultiMap<QString, QString>& _connectionParen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return globalTransform;
|
return globalTransform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,6 +435,8 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr
|
||||||
hfmModel.originalURL = url;
|
hfmModel.originalURL = url;
|
||||||
|
|
||||||
float unitScaleFactor = 1.0f;
|
float unitScaleFactor = 1.0f;
|
||||||
|
glm::quat upAxisZRotation;
|
||||||
|
bool applyUpAxisZRotation = false;
|
||||||
glm::vec3 ambientColor;
|
glm::vec3 ambientColor;
|
||||||
QString hifiGlobalNodeID;
|
QString hifiGlobalNodeID;
|
||||||
unsigned int meshIndex = 0;
|
unsigned int meshIndex = 0;
|
||||||
|
@ -473,11 +474,22 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr
|
||||||
if (subobject.name == propertyName) {
|
if (subobject.name == propertyName) {
|
||||||
static const QVariant UNIT_SCALE_FACTOR = QByteArray("UnitScaleFactor");
|
static const QVariant UNIT_SCALE_FACTOR = QByteArray("UnitScaleFactor");
|
||||||
static const QVariant AMBIENT_COLOR = QByteArray("AmbientColor");
|
static const QVariant AMBIENT_COLOR = QByteArray("AmbientColor");
|
||||||
|
static const QVariant UP_AXIS = QByteArray("UpAxis");
|
||||||
const auto& subpropName = subobject.properties.at(0);
|
const auto& subpropName = subobject.properties.at(0);
|
||||||
if (subpropName == UNIT_SCALE_FACTOR) {
|
if (subpropName == UNIT_SCALE_FACTOR) {
|
||||||
unitScaleFactor = subobject.properties.at(index).toFloat();
|
unitScaleFactor = subobject.properties.at(index).toFloat();
|
||||||
} else if (subpropName == AMBIENT_COLOR) {
|
} else if (subpropName == AMBIENT_COLOR) {
|
||||||
ambientColor = getVec3(subobject.properties, index);
|
ambientColor = getVec3(subobject.properties, index);
|
||||||
|
} else if (subpropName == UP_AXIS) {
|
||||||
|
constexpr int UP_AXIS_Y = 1;
|
||||||
|
constexpr int UP_AXIS_Z = 2;
|
||||||
|
int upAxis = subobject.properties.at(index).toInt();
|
||||||
|
if (upAxis == UP_AXIS_Y) {
|
||||||
|
// No update necessary, y up is the default
|
||||||
|
} else if (upAxis == UP_AXIS_Z) {
|
||||||
|
upAxisZRotation = glm::angleAxis(glm::radians(-90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
|
||||||
|
applyUpAxisZRotation = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1269,9 +1281,11 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr
|
||||||
joint.geometricScaling = fbxModel.geometricScaling;
|
joint.geometricScaling = fbxModel.geometricScaling;
|
||||||
joint.isSkeletonJoint = fbxModel.isLimbNode;
|
joint.isSkeletonJoint = fbxModel.isLimbNode;
|
||||||
hfmModel.hasSkeletonJoints = (hfmModel.hasSkeletonJoints || joint.isSkeletonJoint);
|
hfmModel.hasSkeletonJoints = (hfmModel.hasSkeletonJoints || joint.isSkeletonJoint);
|
||||||
|
if (applyUpAxisZRotation && joint.parentIndex == -1) {
|
||||||
|
joint.rotation *= upAxisZRotation;
|
||||||
|
joint.translation = upAxisZRotation * joint.translation;
|
||||||
|
}
|
||||||
glm::quat combinedRotation = joint.preRotation * joint.rotation * joint.postRotation;
|
glm::quat combinedRotation = joint.preRotation * joint.rotation * joint.postRotation;
|
||||||
|
|
||||||
if (joint.parentIndex == -1) {
|
if (joint.parentIndex == -1) {
|
||||||
joint.transform = hfmModel.offset * glm::translate(joint.translation) * joint.preTransform *
|
joint.transform = hfmModel.offset * glm::translate(joint.translation) * joint.preTransform *
|
||||||
glm::mat4_cast(combinedRotation) * joint.postTransform;
|
glm::mat4_cast(combinedRotation) * joint.postTransform;
|
||||||
|
@ -1664,6 +1678,14 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (applyUpAxisZRotation) {
|
||||||
|
hfmModelPtr->meshExtents.transform(glm::mat4_cast(upAxisZRotation));
|
||||||
|
hfmModelPtr->bindExtents.transform(glm::mat4_cast(upAxisZRotation));
|
||||||
|
for (auto &mesh : hfmModelPtr->meshes) {
|
||||||
|
mesh.modelTransform *= glm::mat4_cast(upAxisZRotation);
|
||||||
|
mesh.meshExtents.transform(glm::mat4_cast(upAxisZRotation));
|
||||||
|
}
|
||||||
|
}
|
||||||
return hfmModelPtr;
|
return hfmModelPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -353,16 +353,19 @@ QSharedPointer<Resource> ResourceCache::getResource(const QUrl& url, const QUrl&
|
||||||
// We've seen this extra info before
|
// We've seen this extra info before
|
||||||
resource = resourcesWithExtraHashIter.value().lock();
|
resource = resourcesWithExtraHashIter.value().lock();
|
||||||
} else if (resourcesWithExtraHash.size() > 0.0f) {
|
} else if (resourcesWithExtraHash.size() > 0.0f) {
|
||||||
// We haven't seen this extra info before, but we've already downloaded the resource. We need a new copy of this object (with any old hash).
|
auto oldResource = resourcesWithExtraHash.begin().value().lock();
|
||||||
resource = createResourceCopy(resourcesWithExtraHash.begin().value().lock());
|
if (oldResource) {
|
||||||
resource->setExtra(extra);
|
// We haven't seen this extra info before, but we've already downloaded the resource. We need a new copy of this object (with any old hash).
|
||||||
resource->setExtraHash(extraHash);
|
resource = createResourceCopy(oldResource);
|
||||||
resource->setSelf(resource);
|
resource->setExtra(extra);
|
||||||
resource->setCache(this);
|
resource->setExtraHash(extraHash);
|
||||||
resource->moveToThread(qApp->thread());
|
resource->setSelf(resource);
|
||||||
connect(resource.data(), &Resource::updateSize, this, &ResourceCache::updateTotalSize);
|
resource->setCache(this);
|
||||||
resourcesWithExtraHash.insert(extraHash, resource);
|
resource->moveToThread(qApp->thread());
|
||||||
resource->ensureLoading();
|
connect(resource.data(), &Resource::updateSize, this, &ResourceCache::updateTotalSize);
|
||||||
|
resourcesWithExtraHash.insert(extraHash, resource);
|
||||||
|
resource->ensureLoading();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (resource) {
|
if (resource) {
|
||||||
|
|
|
@ -31,7 +31,6 @@ using namespace udt;
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
|
|
||||||
Connection::Connection(Socket* parentSocket, HifiSockAddr destination, std::unique_ptr<CongestionControl> congestionControl) :
|
Connection::Connection(Socket* parentSocket, HifiSockAddr destination, std::unique_ptr<CongestionControl> congestionControl) :
|
||||||
QObject(parentSocket),
|
|
||||||
_parentSocket(parentSocket),
|
_parentSocket(parentSocket),
|
||||||
_destination(destination),
|
_destination(destination),
|
||||||
_congestionControl(move(congestionControl))
|
_congestionControl(move(congestionControl))
|
||||||
|
|
|
@ -251,7 +251,10 @@ Connection* Socket::findOrCreateConnection(const HifiSockAddr& sockAddr, bool fi
|
||||||
auto congestionControl = _ccFactory->create();
|
auto congestionControl = _ccFactory->create();
|
||||||
congestionControl->setMaxBandwidth(_maxBandwidth);
|
congestionControl->setMaxBandwidth(_maxBandwidth);
|
||||||
auto connection = std::unique_ptr<Connection>(new Connection(this, sockAddr, std::move(congestionControl)));
|
auto connection = std::unique_ptr<Connection>(new Connection(this, sockAddr, std::move(congestionControl)));
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
qCDebug(networking) << "Moving new Connection to NodeList thread";
|
||||||
|
connection->moveToThread(thread());
|
||||||
|
}
|
||||||
// allow higher-level classes to find out when connections have completed a handshake
|
// allow higher-level classes to find out when connections have completed a handshake
|
||||||
QObject::connect(connection.get(), &Connection::receiverHandshakeRequestComplete,
|
QObject::connect(connection.get(), &Connection::receiverHandshakeRequestComplete,
|
||||||
this, &Socket::clientHandshakeRequestComplete);
|
this, &Socket::clientHandshakeRequestComplete);
|
||||||
|
|
|
@ -149,7 +149,7 @@ public:
|
||||||
|
|
||||||
OctreeElementPointer getRoot() { return _rootElement; }
|
OctreeElementPointer getRoot() { return _rootElement; }
|
||||||
|
|
||||||
virtual void eraseNonLocalEntities() { _isDirty = true; };
|
virtual void eraseDomainAndNonOwnedEntities() { _isDirty = true; };
|
||||||
virtual void eraseAllOctreeElements(bool createNewRoot = true);
|
virtual void eraseAllOctreeElements(bool createNewRoot = true);
|
||||||
|
|
||||||
virtual void readBitstreamToTree(const unsigned char* bitstream, uint64_t bufferSizeBytes, ReadBitstreamToTreeParams& args);
|
virtual void readBitstreamToTree(const unsigned char* bitstream, uint64_t bufferSizeBytes, ReadBitstreamToTreeParams& args);
|
||||||
|
|
|
@ -198,10 +198,10 @@ void OctreeProcessor::processDatagram(ReceivedMessage& message, SharedNodePointe
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void OctreeProcessor::clearNonLocalEntities() {
|
void OctreeProcessor::clearDomainAndNonOwnedEntities() {
|
||||||
if (_tree) {
|
if (_tree) {
|
||||||
_tree->withWriteLock([&] {
|
_tree->withWriteLock([&] {
|
||||||
_tree->eraseNonLocalEntities();
|
_tree->eraseDomainAndNonOwnedEntities();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ public:
|
||||||
virtual void init();
|
virtual void init();
|
||||||
|
|
||||||
/// clears the tree
|
/// clears the tree
|
||||||
virtual void clearNonLocalEntities();
|
virtual void clearDomainAndNonOwnedEntities();
|
||||||
virtual void clear();
|
virtual void clear();
|
||||||
|
|
||||||
float getAverageElementsPerPacket() const { return _elementsPerPacket.getAverage(); }
|
float getAverageElementsPerPacket() const { return _elementsPerPacket.getAverage(); }
|
||||||
|
|
|
@ -1346,14 +1346,19 @@ void Model::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::computeMeshPartLocalBounds() {
|
void Model::computeMeshPartLocalBounds() {
|
||||||
for (auto& part : _modelMeshRenderItems) {
|
render::Transaction transaction;
|
||||||
const Model::MeshState& state = _meshStates.at(part->_meshIndex);
|
auto meshStates = _meshStates;
|
||||||
if (_useDualQuaternionSkinning) {
|
for (auto renderItem : _modelMeshRenderItemIDs) {
|
||||||
part->computeAdjustedLocalBound(state.clusterDualQuaternions);
|
transaction.updateItem<ModelMeshPartPayload>(renderItem, [this, meshStates](ModelMeshPartPayload& data) {
|
||||||
} else {
|
const Model::MeshState& state = meshStates.at(data._meshIndex);
|
||||||
part->computeAdjustedLocalBound(state.clusterMatrices);
|
if (_useDualQuaternionSkinning) {
|
||||||
}
|
data.computeAdjustedLocalBound(state.clusterDualQuaternions);
|
||||||
|
} else {
|
||||||
|
data.computeAdjustedLocalBound(state.clusterMatrices);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
// virtual
|
// virtual
|
||||||
|
|
|
@ -976,7 +976,9 @@ void ScriptEngine::addEventHandler(const EntityItemID& entityID, const QString&
|
||||||
using PointerHandler = std::function<void(const EntityItemID&, const PointerEvent&)>;
|
using PointerHandler = std::function<void(const EntityItemID&, const PointerEvent&)>;
|
||||||
auto makePointerHandler = [this](QString eventName) -> PointerHandler {
|
auto makePointerHandler = [this](QString eventName) -> PointerHandler {
|
||||||
return [this, eventName](const EntityItemID& entityItemID, const PointerEvent& event) {
|
return [this, eventName](const EntityItemID& entityItemID, const PointerEvent& event) {
|
||||||
forwardHandlerCall(entityItemID, eventName, { entityItemID.toScriptValue(this), event.toScriptValue(this) });
|
if (!EntityTree::areEntityClicksCaptured()) {
|
||||||
|
forwardHandlerCall(entityItemID, eventName, { entityItemID.toScriptValue(this), event.toScriptValue(this) });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,20 @@
|
||||||
100,
|
100,
|
||||||
makeLaserParams((this.hand + HUD_LASER_OFFSET), false));
|
makeLaserParams((this.hand + HUD_LASER_OFFSET), false));
|
||||||
|
|
||||||
|
this.getFarGrab = function () {
|
||||||
|
return getEnabledModuleByName(this.hand === RIGHT_HAND ? ("RightFarGrabEntity") : ("LeftFarGrabEntity"));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.farGrabActive = function () {
|
||||||
|
var farGrab = this.getFarGrab();
|
||||||
|
// farGrab will be null if module isn't loaded.
|
||||||
|
if (farGrab) {
|
||||||
|
return farGrab.targetIsNull();
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
this.getOtherHandController = function() {
|
this.getOtherHandController = function() {
|
||||||
return (this.hand === RIGHT_HAND) ? Controller.Standard.LeftHand : Controller.Standard.RightHand;
|
return (this.hand === RIGHT_HAND) ? Controller.Standard.LeftHand : Controller.Standard.RightHand;
|
||||||
};
|
};
|
||||||
|
@ -79,7 +93,7 @@
|
||||||
|
|
||||||
this.isReady = function (controllerData) {
|
this.isReady = function (controllerData) {
|
||||||
var otherModuleRunning = this.getOtherModule().running;
|
var otherModuleRunning = this.getOtherModule().running;
|
||||||
if (!otherModuleRunning && HMD.active) {
|
if (!otherModuleRunning && HMD.active && !this.farGrabActive()) {
|
||||||
if (this.processLaser(controllerData)) {
|
if (this.processLaser(controllerData)) {
|
||||||
this.running = true;
|
this.running = true;
|
||||||
return ControllerDispatcherUtils.makeRunningValues(true, [], []);
|
return ControllerDispatcherUtils.makeRunningValues(true, [], []);
|
||||||
|
|
|
@ -37,6 +37,20 @@ Script.include("/~/system/libraries/controllers.js");
|
||||||
100,
|
100,
|
||||||
makeLaserParams(hand, true));
|
makeLaserParams(hand, true));
|
||||||
|
|
||||||
|
this.getFarGrab = function () {
|
||||||
|
return getEnabledModuleByName(this.hand === RIGHT_HAND ? ("RightFarGrabEntity") : ("LeftFarGrabEntity"));
|
||||||
|
};
|
||||||
|
|
||||||
|
this.farGrabActive = function () {
|
||||||
|
var farGrab = this.getFarGrab();
|
||||||
|
// farGrab will be null if module isn't loaded.
|
||||||
|
if (farGrab) {
|
||||||
|
return farGrab.targetIsNull();
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
this.grabModuleWantsNearbyOverlay = function(controllerData) {
|
this.grabModuleWantsNearbyOverlay = function(controllerData) {
|
||||||
if (controllerData.triggerValues[this.hand] > TRIGGER_ON_VALUE || controllerData.secondaryValues[this.hand] > BUMPER_ON_VALUE) {
|
if (controllerData.triggerValues[this.hand] > TRIGGER_ON_VALUE || controllerData.secondaryValues[this.hand] > BUMPER_ON_VALUE) {
|
||||||
var nearGrabName = this.hand === RIGHT_HAND ? "RightNearParentingGrabOverlay" : "LeftNearParentingGrabOverlay";
|
var nearGrabName = this.hand === RIGHT_HAND ? "RightNearParentingGrabOverlay" : "LeftNearParentingGrabOverlay";
|
||||||
|
@ -184,7 +198,12 @@ Script.include("/~/system/libraries/controllers.js");
|
||||||
|
|
||||||
this.dominantHandOverride = false;
|
this.dominantHandOverride = false;
|
||||||
|
|
||||||
this.isReady = function(controllerData) {
|
this.isReady = function (controllerData) {
|
||||||
|
// Trivial rejection for when FarGrab is active.
|
||||||
|
if (this.farGrabActive()) {
|
||||||
|
return makeRunningValues(false, [], []);
|
||||||
|
}
|
||||||
|
|
||||||
var isTriggerPressed = controllerData.triggerValues[this.hand] > TRIGGER_OFF_VALUE &&
|
var isTriggerPressed = controllerData.triggerValues[this.hand] > TRIGGER_OFF_VALUE &&
|
||||||
controllerData.triggerValues[this.otherHand] <= TRIGGER_OFF_VALUE;
|
controllerData.triggerValues[this.otherHand] <= TRIGGER_OFF_VALUE;
|
||||||
var type = this.getInteractableType(controllerData, isTriggerPressed, false);
|
var type = this.getInteractableType(controllerData, isTriggerPressed, false);
|
||||||
|
|
|
@ -418,13 +418,11 @@ resizeTablet = function (width, newParentJointIndex, sensorToWorldScaleOverride)
|
||||||
var HOME_BUTTON_Z_OFFSET = (tabletDepth / 1.9) * sensorScaleOffsetOverride;
|
var HOME_BUTTON_Z_OFFSET = (tabletDepth / 1.9) * sensorScaleOffsetOverride;
|
||||||
Entities.editEntity(HMD.homeButtonID, {
|
Entities.editEntity(HMD.homeButtonID, {
|
||||||
localPosition: { x: HOME_BUTTON_X_OFFSET, y: HOME_BUTTON_Y_OFFSET, z: -HOME_BUTTON_Z_OFFSET },
|
localPosition: { x: HOME_BUTTON_X_OFFSET, y: HOME_BUTTON_Y_OFFSET, z: -HOME_BUTTON_Z_OFFSET },
|
||||||
localRotation: { x: 0, y: 1, z: 0, w: 0 },
|
|
||||||
dimensions: { x: homeButtonDim, y: homeButtonDim, z: homeButtonDim }
|
dimensions: { x: homeButtonDim, y: homeButtonDim, z: homeButtonDim }
|
||||||
});
|
});
|
||||||
|
|
||||||
Entities.editEntity(HMD.homeButtonHighlightID, {
|
Entities.editEntity(HMD.homeButtonHighlightID, {
|
||||||
localPosition: { x: -HOME_BUTTON_X_OFFSET, y: HOME_BUTTON_Y_OFFSET, z: -HOME_BUTTON_Z_OFFSET },
|
localPosition: { x: -HOME_BUTTON_X_OFFSET, y: HOME_BUTTON_Y_OFFSET, z: -HOME_BUTTON_Z_OFFSET },
|
||||||
localRotation: { x: 0, y: 1, z: 0, w: 0 },
|
|
||||||
dimensions: { x: homeButtonDim, y: homeButtonDim, z: homeButtonDim }
|
dimensions: { x: homeButtonDim, y: homeButtonDim, z: homeButtonDim }
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -482,13 +480,11 @@ reparentAndScaleTablet = function(width, reparentProps) {
|
||||||
var HOME_BUTTON_Z_OFFSET = (tabletDepth / 1.9) * sensorScaleOffsetOverride;
|
var HOME_BUTTON_Z_OFFSET = (tabletDepth / 1.9) * sensorScaleOffsetOverride;
|
||||||
Entities.editEntity(HMD.homeButtonID, {
|
Entities.editEntity(HMD.homeButtonID, {
|
||||||
localPosition: { x: HOME_BUTTON_X_OFFSET, y: HOME_BUTTON_Y_OFFSET, z: -HOME_BUTTON_Z_OFFSET },
|
localPosition: { x: HOME_BUTTON_X_OFFSET, y: HOME_BUTTON_Y_OFFSET, z: -HOME_BUTTON_Z_OFFSET },
|
||||||
localRotation: { x: 0, y: 1, z: 0, w: 0 },
|
|
||||||
dimensions: { x: homeButtonDim, y: homeButtonDim, z: homeButtonDim }
|
dimensions: { x: homeButtonDim, y: homeButtonDim, z: homeButtonDim }
|
||||||
});
|
});
|
||||||
|
|
||||||
Entities.editEntity(HMD.homeButtonHighlightID, {
|
Entities.editEntity(HMD.homeButtonHighlightID, {
|
||||||
localPosition: { x: -HOME_BUTTON_X_OFFSET, y: HOME_BUTTON_Y_OFFSET, z: -HOME_BUTTON_Z_OFFSET },
|
localPosition: { x: -HOME_BUTTON_X_OFFSET, y: HOME_BUTTON_Y_OFFSET, z: -HOME_BUTTON_Z_OFFSET },
|
||||||
localRotation: { x: 0, y: 1, z: 0, w: 0 },
|
|
||||||
dimensions: { x: homeButtonDim, y: homeButtonDim, z: homeButtonDim }
|
dimensions: { x: homeButtonDim, y: homeButtonDim, z: homeButtonDim }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue