mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-04-14 08:16:03 +02:00
Merge remote-tracking branch 'upstream/master' into ikEnabledFix
This commit is contained in:
commit
48f512a553
21 changed files with 242 additions and 296 deletions
|
@ -16,8 +16,8 @@
|
|||
#include <QObject>
|
||||
|
||||
/**jsdoc
|
||||
* 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.
|
||||
* The <code>HifiAbout</code> API provides information about the version of Interface that is currently running. It also
|
||||
* has the functionality to open a web page in an Interface browser window.
|
||||
*
|
||||
* @namespace HifiAbout
|
||||
*
|
||||
|
@ -30,9 +30,9 @@
|
|||
* @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>
|
||||
* print("HiFi build date: " + HifiAbout.buildDate); // 11 Feb 2019
|
||||
* print("HiFi version: " + HifiAbout.buildVersion); // 0.78.0
|
||||
* print("Qt version: " + HifiAbout.qtVersion); // 5.10.1
|
||||
* 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); // Returns the build version of Interface currently running on your machine.
|
||||
* print("Qt version: " + HifiAbout.qtVersion); // Returns the Qt version details of the version of Interface currently running on your machine.
|
||||
*/
|
||||
|
||||
class AboutUtil : public QObject {
|
||||
|
@ -52,9 +52,9 @@ public:
|
|||
public slots:
|
||||
|
||||
/**jsdoc
|
||||
* Display a Web page in an Interface browser window.
|
||||
* Display a web page in an Interface browser window.
|
||||
* @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;
|
||||
private:
|
||||
|
|
|
@ -1061,6 +1061,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
connect(PluginManager::getInstance().data(), &PluginManager::inputDeviceRunningChanged,
|
||||
controllerScriptingInterface, &controller::ScriptingInterface::updateRunningInputDevices);
|
||||
|
||||
EntityTree::setEntityClicksCapturedOperator([this] {
|
||||
return _controllerScriptingInterface->areEntityClicksCaptured();
|
||||
});
|
||||
|
||||
_entityClipboard->createRootElement();
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
|
@ -4392,7 +4396,6 @@ void Application::mouseMoveEvent(QMouseEvent* event) {
|
|||
if (compositor.getReticleVisible() || !isHMDMode() || !compositor.getReticleOverDesktop() ||
|
||||
getOverlays().getOverlayAtPoint(glm::vec2(transformedPos.x(), transformedPos.y())) != UNKNOWN_ENTITY_ID) {
|
||||
getEntities()->mouseMoveEvent(&mappedEvent);
|
||||
getOverlays().mouseMoveEvent(&mappedEvent);
|
||||
}
|
||||
|
||||
_controllerScriptingInterface->emitMouseMoveEvent(&mappedEvent); // send events to any registered scripts
|
||||
|
@ -4426,14 +4429,8 @@ void Application::mousePressEvent(QMouseEvent* event) {
|
|||
#endif
|
||||
|
||||
QMouseEvent mappedEvent(event->type(), transformedPos, event->screenPos(), event->button(), event->buttons(), event->modifiers());
|
||||
std::pair<float, QUuid> entityResult;
|
||||
if (!_controllerScriptingInterface->areEntityClicksCaptured()) {
|
||||
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);
|
||||
QUuid result = getEntities()->mousePressEvent(&mappedEvent);
|
||||
setKeyboardFocusEntity(getEntities()->wantsKeyboardFocus(result) ? result : UNKNOWN_ENTITY_ID);
|
||||
|
||||
_controllerScriptingInterface->emitMousePressEvent(&mappedEvent); // send events to any registered scripts
|
||||
|
||||
|
@ -4472,11 +4469,7 @@ void Application::mouseDoublePressEvent(QMouseEvent* event) {
|
|||
transformedPos,
|
||||
event->screenPos(), event->button(),
|
||||
event->buttons(), event->modifiers());
|
||||
|
||||
if (!_controllerScriptingInterface->areEntityClicksCaptured()) {
|
||||
getEntities()->mouseDoublePressEvent(&mappedEvent);
|
||||
}
|
||||
getOverlays().mouseDoublePressEvent(&mappedEvent);
|
||||
getEntities()->mouseDoublePressEvent(&mappedEvent);
|
||||
|
||||
// if one of our scripts have asked to capture this event, then stop processing it
|
||||
if (_controllerScriptingInterface->isMouseCaptured()) {
|
||||
|
@ -4501,7 +4494,6 @@ void Application::mouseReleaseEvent(QMouseEvent* event) {
|
|||
event->buttons(), event->modifiers());
|
||||
|
||||
getEntities()->mouseReleaseEvent(&mappedEvent);
|
||||
getOverlays().mouseReleaseEvent(&mappedEvent);
|
||||
|
||||
_controllerScriptingInterface->emitMouseReleaseEvent(&mappedEvent); // send events to any registered scripts
|
||||
|
||||
|
@ -6951,7 +6943,7 @@ void Application::clearDomainOctreeDetails(bool clearAll) {
|
|||
});
|
||||
|
||||
// reset the model renderer
|
||||
clearAll ? getEntities()->clear() : getEntities()->clearNonLocalEntities();
|
||||
clearAll ? getEntities()->clear() : getEntities()->clearDomainAndNonOwnedEntities();
|
||||
|
||||
auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
|
||||
|
||||
|
|
|
@ -62,8 +62,8 @@ public:
|
|||
* <tr><th>Value</th><th>Meaning</th><th>Description</th></tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr><td><code>0</code></td><td>Not logged in</td><td>The user isn't 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>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 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
|
||||
* 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,
|
||||
|
@ -73,8 +73,8 @@ public:
|
|||
* <tr><td><code>5</code></td><td>Ready</td><td>The wallet is ready for use.</td></tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
* <p>Wallets used to be stored locally but now they're stored on the server, unless the computer once had a wallet stored
|
||||
* locally in which case the wallet may be present in both places.</p>
|
||||
* <p>Wallets used to be stored locally but now they're only stored on the server. A wallet is present in both places if
|
||||
* your computer previously stored its information locally.</p>
|
||||
* @typedef {number} WalletScriptingInterface.WalletStatus
|
||||
*/
|
||||
enum WalletStatus {
|
||||
|
|
|
@ -115,8 +115,8 @@ DownloadInfoResult::DownloadInfoResult() :
|
|||
/**jsdoc
|
||||
* Information on the assets currently being downloaded and pending download.
|
||||
* @typedef {object} AccountServices.DownloadInfoResult
|
||||
* @property {number[]} downloading - The percentage complete for each asset currently being downloaded.
|
||||
* @property {number} pending - The number of assets waiting to be download.
|
||||
* @property {number[]} downloading - The download percentage remaining of each asset currently downloading.
|
||||
* @property {number} pending - The number of assets pending download.
|
||||
*/
|
||||
QScriptValue DownloadInfoResultToScriptValue(QScriptEngine* engine, const DownloadInfoResult& result) {
|
||||
QScriptValue object = engine->newObject();
|
||||
|
|
|
@ -38,19 +38,19 @@ class AccountServicesScriptingInterface : public QObject {
|
|||
Q_OBJECT
|
||||
|
||||
/**jsdoc
|
||||
* The <code>AccountServices</code> API provides functions related to user connectivity, visibility, and asset download
|
||||
* progress.
|
||||
* The <code>AccountServices</code> API provides functions that give information on user connectivity, visibility, and
|
||||
* asset download progress.
|
||||
*
|
||||
* @hifi-interface
|
||||
* @hifi-client-entity
|
||||
* @hifi-avatar
|
||||
*
|
||||
* @namespace AccountServices
|
||||
* @property {string} username - The user name if the user is logged in, otherwise <code>"Unknown user"</code>.
|
||||
* <em>Read-only.</em>
|
||||
* @property {string} username - The user name of the user logged in. If there is no user logged in, it is
|
||||
* <code>"Unknown user"</code>. <em>Read-only.</em>
|
||||
* @property {boolean} loggedIn - <code>true</code> if the user is logged in, otherwise <code>false</code>.
|
||||
* <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>"friends"</code> - user is visible only to friends.<br />
|
||||
* <code>"connections"</code> - user is visible to friends and connections.<br />
|
||||
|
@ -74,23 +74,23 @@ public:
|
|||
public slots:
|
||||
|
||||
/**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
|
||||
* @returns {AccountServices.DownloadInfoResult} Information on the progress of assets download.
|
||||
* @returns {AccountServices.DownloadInfoResult} Information on the download progress of assets.
|
||||
*/
|
||||
DownloadInfoResult getDownloadInfo();
|
||||
|
||||
/**jsdoc
|
||||
* Cause a {@link AccountServices.downloadInfoChanged|downloadInfoChanged} signal to be triggered with information on the
|
||||
* current progress of the download of assets in the domain.
|
||||
* Triggers a {@link AccountServices.downloadInfoChanged|downloadInfoChanged} signal with information on the current
|
||||
* download progress of the assets in the domain.
|
||||
* @function AccountServices.updateDownloadInfo
|
||||
*/
|
||||
void updateDownloadInfo();
|
||||
|
||||
/**jsdoc
|
||||
* Check whether the user is logged in.
|
||||
* Checks whether the user is logged in.
|
||||
* @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>
|
||||
* var isLoggedIn = AccountServices.isLoggedIn();
|
||||
* print("You are logged in: " + isLoggedIn); // true or false
|
||||
|
@ -98,9 +98,9 @@ public slots:
|
|||
bool isLoggedIn();
|
||||
|
||||
/**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
|
||||
* @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();
|
||||
|
||||
|
@ -140,7 +140,7 @@ signals:
|
|||
/**jsdoc
|
||||
* Triggered when the username logged in with changes, i.e., when the user logs in or out.
|
||||
* @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}
|
||||
* @example <caption>Report when your username changes.</caption>
|
||||
* AccountServices.myUsernameChanged.connect(function (username) {
|
||||
|
@ -150,9 +150,9 @@ signals:
|
|||
void myUsernameChanged(const QString& username);
|
||||
|
||||
/**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
|
||||
* @param {AccountServices.DownloadInfoResult} downloadInfo - Information on the progress of assets download.
|
||||
* @param {AccountServices.DownloadInfoResult} downloadInfo - Information on the download progress of assets.
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void downloadInfoChanged(DownloadInfoResult info);
|
||||
|
@ -186,7 +186,7 @@ signals:
|
|||
/**jsdoc
|
||||
* Triggered when the login status of the user changes.
|
||||
* @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}
|
||||
* @example <caption>Report when your login status changes.</caption>
|
||||
* 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 {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
|
||||
* Store version of Interface runs in limited commerce mode. <em>Read-only.</em>
|
||||
* mode, certain Interface functionalities are disabled, e.g., users can't buy items that are not free from the Marketplace.
|
||||
* The Oculus Store version of Interface runs in limited commerce mode. <em>Read-only.</em>
|
||||
*/
|
||||
class WalletScriptingInterface : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
|
@ -55,16 +55,16 @@ public:
|
|||
WalletScriptingInterface();
|
||||
|
||||
/**jsdoc
|
||||
* Check and update the user's wallet status.
|
||||
* Checks and updates the user's wallet status.
|
||||
* @function WalletScriptingInterface.refreshWalletStatus
|
||||
*/
|
||||
Q_INVOKABLE void refreshWalletStatus();
|
||||
|
||||
/**jsdoc
|
||||
* Get the current status of the user's wallet.
|
||||
* Gets the current status of the user's wallet.
|
||||
* @function WalletScriptingInterface.getWalletStatus
|
||||
* @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.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
|
||||
* the {@link WalletScriptingInterface.ownershipVerificationSuccess|ownershipVerificationSuccess} and
|
||||
* {@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
|
||||
* entity.
|
||||
* <strong>Warning:</strong> Neither of these signals are triggered if the entity is not an avatar entity or is not
|
||||
* certified.
|
||||
* @function WalletScriptingInterface.proveAvatarEntityOwnershipVerification
|
||||
* @param {Uuid} entityID - The ID of the avatar entity to check.
|
||||
* @example <caption>Check ownership of all nearby certified avatar entities.</caption>
|
||||
* @param {Uuid} entityID - The avatar entity's ID.
|
||||
* @example <caption>Check the ownership of all nearby certified avatar entities.</caption>
|
||||
* // Set up response handling.
|
||||
* function ownershipSuccess(entityID) {
|
||||
* print("Ownership test succeeded for: " + entityID);
|
||||
|
@ -118,7 +118,7 @@ public:
|
|||
signals:
|
||||
|
||||
/**jsdoc
|
||||
* Triggered when the status of the user's wallet changes.
|
||||
* Triggered when the user's wallet status changes.
|
||||
* @function WalletScriptingInterface.walletStatusChanged
|
||||
* @returns {Signal}
|
||||
* @example <caption>Report when your wallet status changes, e.g., when you log in and out.</caption>
|
||||
|
@ -136,7 +136,7 @@ signals:
|
|||
void limitedCommerceChanged();
|
||||
|
||||
/**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.
|
||||
* @function WalletScriptingInterface.walletNotSetup
|
||||
* @returns {Signal}
|
||||
|
|
|
@ -43,14 +43,6 @@ std::unordered_map<QString, QString> Overlays::_entityToOverlayTypes;
|
|||
std::unordered_map<QString, QString> Overlays::_overlayToEntityTypes;
|
||||
|
||||
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(Sphere, sphere);
|
||||
_overlayToEntityTypes["rectangle3d"] = "Shape";
|
||||
|
@ -81,13 +73,23 @@ void Overlays::cleanupAllOverlays() {
|
|||
|
||||
void Overlays::init() {
|
||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>().data();
|
||||
auto pointerManager = DependencyManager::get<PointerManager>();
|
||||
connect(pointerManager.data(), &PointerManager::hoverBeginOverlay, entityScriptingInterface , &EntityScriptingInterface::hoverEnterEntity);
|
||||
connect(pointerManager.data(), &PointerManager::hoverContinueOverlay, entityScriptingInterface, &EntityScriptingInterface::hoverOverEntity);
|
||||
connect(pointerManager.data(), &PointerManager::hoverEndOverlay, entityScriptingInterface, &EntityScriptingInterface::hoverLeaveEntity);
|
||||
connect(pointerManager.data(), &PointerManager::triggerBeginOverlay, entityScriptingInterface, &EntityScriptingInterface::mousePressOnEntity);
|
||||
connect(pointerManager.data(), &PointerManager::triggerContinueOverlay, entityScriptingInterface, &EntityScriptingInterface::mouseMoveOnEntity);
|
||||
connect(pointerManager.data(), &PointerManager::triggerEndOverlay, entityScriptingInterface, &EntityScriptingInterface::mouseReleaseOnEntity);
|
||||
auto pointerManager = DependencyManager::get<PointerManager>().data();
|
||||
connect(pointerManager, &PointerManager::hoverBeginOverlay, entityScriptingInterface , &EntityScriptingInterface::hoverEnterEntity);
|
||||
connect(pointerManager, &PointerManager::hoverContinueOverlay, entityScriptingInterface, &EntityScriptingInterface::hoverOverEntity);
|
||||
connect(pointerManager, &PointerManager::hoverEndOverlay, entityScriptingInterface, &EntityScriptingInterface::hoverLeaveEntity);
|
||||
connect(pointerManager, &PointerManager::triggerBeginOverlay, entityScriptingInterface, &EntityScriptingInterface::mousePressOnEntity);
|
||||
connect(pointerManager, &PointerManager::triggerContinueOverlay, entityScriptingInterface, &EntityScriptingInterface::mouseMoveOnEntity);
|
||||
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) {
|
||||
|
@ -1159,7 +1161,7 @@ bool Overlays::isAddedOverlay(const QUuid& id) {
|
|||
}
|
||||
|
||||
void Overlays::sendMousePressOnOverlay(const QUuid& id, const PointerEvent& event) {
|
||||
mousePressPointerEvent(id, event);
|
||||
mousePressOnPointerEvent(id, event);
|
||||
}
|
||||
|
||||
void Overlays::sendMouseReleaseOnOverlay(const QUuid& id, const PointerEvent& event) {
|
||||
|
@ -1206,57 +1208,66 @@ float Overlays::height() {
|
|||
return offscreenUi->getWindow()->size().height();
|
||||
}
|
||||
|
||||
static uint32_t toPointerButtons(const QMouseEvent& event) {
|
||||
uint32_t buttons = 0;
|
||||
buttons |= event.buttons().testFlag(Qt::LeftButton) ? PointerEvent::PrimaryButton : 0;
|
||||
buttons |= event.buttons().testFlag(Qt::RightButton) ? PointerEvent::SecondaryButton : 0;
|
||||
buttons |= event.buttons().testFlag(Qt::MiddleButton) ? PointerEvent::TertiaryButton : 0;
|
||||
return buttons;
|
||||
}
|
||||
|
||||
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;
|
||||
void Overlays::mousePressOnPointerEvent(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 mousePressOnOverlay(id, event);
|
||||
}
|
||||
}
|
||||
return overlayResult;
|
||||
}
|
||||
|
||||
PointerEvent Overlays::calculateOverlayPointerEvent(const QUuid& id, const PickRay& ray,
|
||||
const RayToOverlayIntersectionResult& rayPickResult, QMouseEvent* event,
|
||||
PointerEvent::EventType eventType) {
|
||||
glm::vec2 pos2D = RayPick::projectOntoEntityXYPlane(id, rayPickResult.intersection);
|
||||
return PointerEvent(eventType, PointerManager::MOUSE_POINTER_ID, pos2D, rayPickResult.intersection, rayPickResult.surfaceNormal,
|
||||
ray.direction, toPointerButton(*event), toPointerButtons(*event), event->modifiers());
|
||||
void Overlays::mousePressOffPointerEvent() {
|
||||
emit mousePressOffOverlay();
|
||||
}
|
||||
|
||||
void Overlays::mouseDoublePressOnPointerEvent(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 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) {
|
||||
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 hoverEnterOverlay(id, event);
|
||||
auto entity = DependencyManager::get<EntityTreeRenderer>()->getEntity(id);
|
||||
if (entity && entity->isLocalEntity()) {
|
||||
emit hoverEnterOverlay(id, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1264,7 +1275,10 @@ void Overlays::hoverOverPointerEvent(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 hoverOverOverlay(id, event);
|
||||
auto entity = DependencyManager::get<EntityTreeRenderer>()->getEntity(id);
|
||||
if (entity && entity->isLocalEntity()) {
|
||||
emit hoverOverOverlay(id, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1272,113 +1286,10 @@ void Overlays::hoverLeavePointerEvent(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 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);
|
||||
auto entity = DependencyManager::get<EntityTreeRenderer>()->getEntity(id);
|
||||
if (entity && entity->isLocalEntity()) {
|
||||
emit hoverLeaveOverlay(id, event);
|
||||
}
|
||||
|
||||
// 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,
|
||||
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();
|
||||
|
||||
mutable QScriptEngine _scriptEngine;
|
||||
|
@ -719,9 +714,6 @@ private:
|
|||
PointerEvent calculateOverlayPointerEvent(const QUuid& id, const PickRay& ray, const RayToOverlayIntersectionResult& rayPickResult,
|
||||
QMouseEvent* event, PointerEvent::EventType eventType);
|
||||
|
||||
QUuid _currentClickingOnOverlayID;
|
||||
QUuid _currentHoverOverOverlayID;
|
||||
|
||||
static QString entityToOverlayType(const QString& type);
|
||||
static QString overlayToEntityType(const QString& type);
|
||||
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());
|
||||
|
||||
private slots:
|
||||
void mousePressPointerEvent(const QUuid& id, const PointerEvent& event);
|
||||
void mouseMovePointerEvent(const QUuid& id, const PointerEvent& event);
|
||||
void mousePressOnPointerEvent(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 mouseMovePointerEvent(const QUuid& id, const PointerEvent& event);
|
||||
void hoverEnterPointerEvent(const QUuid& id, const PointerEvent& event);
|
||||
void hoverOverPointerEvent(const QUuid& id, const PointerEvent& event);
|
||||
void hoverLeavePointerEvent(const QUuid& id, const PointerEvent& event);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#define ADD_TYPE_MAP(entity, overlay) \
|
||||
|
|
|
@ -73,14 +73,14 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf
|
|||
_currentHoverOverEntityID = UNKNOWN_ENTITY_ID;
|
||||
_currentClickingOnEntityID = UNKNOWN_ENTITY_ID;
|
||||
|
||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>().data();
|
||||
auto pointerManager = DependencyManager::get<PointerManager>();
|
||||
connect(pointerManager.data(), &PointerManager::hoverBeginEntity, entityScriptingInterface.data(), &EntityScriptingInterface::hoverEnterEntity);
|
||||
connect(pointerManager.data(), &PointerManager::hoverContinueEntity, entityScriptingInterface.data(), &EntityScriptingInterface::hoverOverEntity);
|
||||
connect(pointerManager.data(), &PointerManager::hoverEndEntity, entityScriptingInterface.data(), &EntityScriptingInterface::hoverLeaveEntity);
|
||||
connect(pointerManager.data(), &PointerManager::triggerBeginEntity, entityScriptingInterface.data(), &EntityScriptingInterface::mousePressOnEntity);
|
||||
connect(pointerManager.data(), &PointerManager::triggerContinueEntity, entityScriptingInterface.data(), &EntityScriptingInterface::mouseMoveOnEntity);
|
||||
connect(pointerManager.data(), &PointerManager::triggerEndEntity, entityScriptingInterface.data(), &EntityScriptingInterface::mouseReleaseOnEntity);
|
||||
connect(pointerManager.data(), &PointerManager::hoverBeginEntity, entityScriptingInterface, &EntityScriptingInterface::hoverEnterEntity);
|
||||
connect(pointerManager.data(), &PointerManager::hoverContinueEntity, entityScriptingInterface, &EntityScriptingInterface::hoverOverEntity);
|
||||
connect(pointerManager.data(), &PointerManager::hoverEndEntity, entityScriptingInterface, &EntityScriptingInterface::hoverLeaveEntity);
|
||||
connect(pointerManager.data(), &PointerManager::triggerBeginEntity, entityScriptingInterface, &EntityScriptingInterface::mousePressOnEntity);
|
||||
connect(pointerManager.data(), &PointerManager::triggerContinueEntity, entityScriptingInterface, &EntityScriptingInterface::mouseMoveOnEntity);
|
||||
connect(pointerManager.data(), &PointerManager::triggerEndEntity, entityScriptingInterface, &EntityScriptingInterface::mouseReleaseOnEntity);
|
||||
|
||||
// Forward mouse events to web entities
|
||||
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));
|
||||
}
|
||||
};
|
||||
connect(entityScriptingInterface.data(), &EntityScriptingInterface::mousePressOnEntity, this, handlePointerEvent);
|
||||
connect(entityScriptingInterface.data(), &EntityScriptingInterface::mouseMoveOnEntity, this, handlePointerEvent);
|
||||
connect(entityScriptingInterface.data(), &EntityScriptingInterface::mouseReleaseOnEntity, this, handlePointerEvent);
|
||||
connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverEnterEntity, this, [&](const QUuid& entityID, const PointerEvent& event) {
|
||||
connect(entityScriptingInterface, &EntityScriptingInterface::mousePressOnEntity, this, handlePointerEvent);
|
||||
connect(entityScriptingInterface, &EntityScriptingInterface::mouseMoveOnEntity, this, handlePointerEvent);
|
||||
connect(entityScriptingInterface, &EntityScriptingInterface::mouseReleaseOnEntity, this, handlePointerEvent);
|
||||
connect(entityScriptingInterface, &EntityScriptingInterface::hoverEnterEntity, this, [&](const QUuid& entityID, const PointerEvent& event) {
|
||||
std::shared_ptr<render::entities::WebEntityRenderer> thisEntity;
|
||||
auto entity = getEntity(entityID);
|
||||
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));
|
||||
}
|
||||
});
|
||||
connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverOverEntity, this, handlePointerEvent);
|
||||
connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverLeaveEntity, this, [&](const QUuid& entityID, const PointerEvent& event) {
|
||||
connect(entityScriptingInterface, &EntityScriptingInterface::hoverOverEntity, this, handlePointerEvent);
|
||||
connect(entityScriptingInterface, &EntityScriptingInterface::hoverLeaveEntity, this, [&](const QUuid& entityID, const PointerEvent& event) {
|
||||
std::shared_ptr<render::entities::WebEntityRenderer> thisEntity;
|
||||
auto entity = getEntity(entityID);
|
||||
if (entity && entity->isVisible() && entity->getType() == EntityTypes::Web) {
|
||||
|
@ -196,8 +196,8 @@ void EntityTreeRenderer::resetEntitiesScriptEngine() {
|
|||
});
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::stopNonLocalEntityScripts() {
|
||||
leaveNonLocalEntities();
|
||||
void EntityTreeRenderer::stopDomainAndNonOwnedEntities() {
|
||||
leaveDomainAndNonOwnedEntities();
|
||||
// unload and stop the engine
|
||||
if (_entitiesScriptEngine) {
|
||||
QList<EntityItemID> entitiesWithEntityScripts = _entitiesScriptEngine->getListOfEntityScriptIDs();
|
||||
|
@ -206,7 +206,7 @@ void EntityTreeRenderer::stopNonLocalEntityScripts() {
|
|||
EntityItemPointer entityItem = getTree()->findEntityByEntityItemID(entityID);
|
||||
|
||||
if (entityItem) {
|
||||
if (!entityItem->isLocalEntity()) {
|
||||
if (!(entityItem->isLocalEntity() || (entityItem->isAvatarEntity() && entityItem->getOwningAvatarID() == getTree()->getMyAvatarSessionUUID()))) {
|
||||
_entitiesScriptEngine->unloadEntityScript(entityID, true);
|
||||
}
|
||||
}
|
||||
|
@ -214,8 +214,8 @@ void EntityTreeRenderer::stopNonLocalEntityScripts() {
|
|||
}
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::clearNonLocalEntities() {
|
||||
stopNonLocalEntityScripts();
|
||||
void EntityTreeRenderer::clearDomainAndNonOwnedEntities() {
|
||||
stopDomainAndNonOwnedEntities();
|
||||
|
||||
std::unordered_map<EntityItemID, EntityRendererPointer> savedEntities;
|
||||
// remove all entities from the scene
|
||||
|
@ -225,7 +225,7 @@ void EntityTreeRenderer::clearNonLocalEntities() {
|
|||
for (const auto& entry : _entitiesInScene) {
|
||||
const auto& renderer = entry.second;
|
||||
const EntityItemPointer& entityItem = renderer->getEntity();
|
||||
if (!entityItem->isLocalEntity()) {
|
||||
if (!(entityItem->isLocalEntity() || (entityItem->isAvatarEntity() && entityItem->getOwningAvatarID() == getTree()->getMyAvatarSessionUUID()))) {
|
||||
renderer->removeFromScene(scene, transaction);
|
||||
} else {
|
||||
savedEntities[entry.first] = entry.second;
|
||||
|
@ -239,7 +239,7 @@ void EntityTreeRenderer::clearNonLocalEntities() {
|
|||
|
||||
_layeredZones.clearNonLocalLayeredZones();
|
||||
|
||||
OctreeProcessor::clearNonLocalEntities();
|
||||
OctreeProcessor::clearDomainAndNonOwnedEntities();
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::clear() {
|
||||
|
@ -655,22 +655,22 @@ bool EntityTreeRenderer::checkEnterLeaveEntities() {
|
|||
return didUpdate;
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::leaveNonLocalEntities() {
|
||||
void EntityTreeRenderer::leaveDomainAndNonOwnedEntities() {
|
||||
if (_tree && !_shuttingDown) {
|
||||
QVector<EntityItemID> currentLocalEntitiesInside;
|
||||
QVector<EntityItemID> currentEntitiesInsideToSave;
|
||||
foreach (const EntityItemID& entityID, _currentEntitiesInside) {
|
||||
EntityItemPointer entityItem = getTree()->findEntityByEntityItemID(entityID);
|
||||
if (!entityItem->isLocalEntity()) {
|
||||
if (!(entityItem->isLocalEntity() || (entityItem->isAvatarEntity() && entityItem->getOwningAvatarID() == getTree()->getMyAvatarSessionUUID()))) {
|
||||
emit leaveEntity(entityID);
|
||||
if (_entitiesScriptEngine) {
|
||||
_entitiesScriptEngine->callEntityScriptMethod(entityID, "leaveEntity");
|
||||
}
|
||||
} else {
|
||||
currentLocalEntitiesInside.push_back(entityID);
|
||||
currentEntitiesInsideToSave.push_back(entityID);
|
||||
}
|
||||
}
|
||||
|
||||
_currentEntitiesInside = currentLocalEntitiesInside;
|
||||
_currentEntitiesInside = currentEntitiesInsideToSave;
|
||||
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
|
||||
// process these events.
|
||||
if (!_tree || _shuttingDown) {
|
||||
return { FLT_MAX, UNKNOWN_ENTITY_ID };
|
||||
return UNKNOWN_ENTITY_ID;
|
||||
}
|
||||
|
||||
PerformanceTimer perfTimer("EntityTreeRenderer::mousePressEvent");
|
||||
|
@ -805,11 +805,13 @@ std::pair<float, QUuid> EntityTreeRenderer::mousePressEvent(QMouseEvent* event)
|
|||
RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID);
|
||||
EntityItemPointer entity;
|
||||
if (rayPickResult.intersects && (entity = getTree()->findEntityByID(rayPickResult.entityID))) {
|
||||
auto properties = entity->getProperties();
|
||||
QString urlString = properties.getHref();
|
||||
QUrl url = QUrl(urlString, QUrl::StrictMode);
|
||||
if (url.isValid() && !url.isEmpty()){
|
||||
DependencyManager::get<AddressManager>()->handleLookupString(urlString);
|
||||
if (!EntityTree::areEntityClicksCaptured()) {
|
||||
auto properties = entity->getProperties();
|
||||
QString urlString = properties.getHref();
|
||||
QUrl url = QUrl(urlString, QUrl::StrictMode);
|
||||
if (url.isValid() && !url.isEmpty()) {
|
||||
DependencyManager::get<AddressManager>()->handleLookupString(urlString);
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec2 pos2D = projectOntoEntityXYPlane(entity, ray, rayPickResult);
|
||||
|
@ -827,10 +829,10 @@ std::pair<float, QUuid> EntityTreeRenderer::mousePressEvent(QMouseEvent* event)
|
|||
_lastPointerEvent = pointerEvent;
|
||||
_lastPointerEventValid = true;
|
||||
|
||||
return { rayPickResult.distance, rayPickResult.entityID };
|
||||
return rayPickResult.entityID;
|
||||
}
|
||||
emit entityScriptingInterface->mousePressOffEntity();
|
||||
return { FLT_MAX, UNKNOWN_ENTITY_ID };
|
||||
return UNKNOWN_ENTITY_ID;
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::mouseDoublePressEvent(QMouseEvent* event) {
|
||||
|
|
|
@ -87,14 +87,14 @@ public:
|
|||
virtual void init() override;
|
||||
|
||||
/// clears the tree
|
||||
virtual void clearNonLocalEntities() override;
|
||||
virtual void clearDomainAndNonOwnedEntities() override;
|
||||
virtual void clear() override;
|
||||
|
||||
/// reloads the entity scripts, calling unload and preload
|
||||
void reloadEntityScripts();
|
||||
|
||||
// event handles which may generate entity related events
|
||||
std::pair<float, QUuid> mousePressEvent(QMouseEvent* event);
|
||||
QUuid mousePressEvent(QMouseEvent* event);
|
||||
void mouseReleaseEvent(QMouseEvent* event);
|
||||
void mouseDoublePressEvent(QMouseEvent* event);
|
||||
void mouseMoveEvent(QMouseEvent* event);
|
||||
|
@ -170,7 +170,7 @@ private:
|
|||
bool findBestZoneAndMaybeContainingEntities(QVector<EntityItemID>* entitiesContainingAvatar = nullptr);
|
||||
|
||||
bool applyLayeredZones();
|
||||
void stopNonLocalEntityScripts();
|
||||
void stopDomainAndNonOwnedEntities();
|
||||
|
||||
void checkAndCallPreload(const EntityItemID& entityID, bool reload = false, bool unloadFirst = false);
|
||||
|
||||
|
@ -179,7 +179,7 @@ private:
|
|||
|
||||
QScriptValueList createEntityArgs(const EntityItemID& entityID);
|
||||
bool checkEnterLeaveEntities();
|
||||
void leaveNonLocalEntities();
|
||||
void leaveDomainAndNonOwnedEntities();
|
||||
void leaveAllEntities();
|
||||
void forceRecheckEntities();
|
||||
|
||||
|
|
|
@ -78,13 +78,14 @@ OctreeElementPointer EntityTree::createNewElement(unsigned char* octalCode) {
|
|||
return std::static_pointer_cast<OctreeElement>(newElement);
|
||||
}
|
||||
|
||||
void EntityTree::eraseNonLocalEntities() {
|
||||
void EntityTree::eraseDomainAndNonOwnedEntities() {
|
||||
emit clearingEntities();
|
||||
|
||||
if (_simulation) {
|
||||
// local entities are not in the simulation, so we clear ALL
|
||||
_simulation->clearEntities();
|
||||
}
|
||||
|
||||
this->withWriteLock([&] {
|
||||
QHash<EntityItemID, EntityItemPointer> savedEntities;
|
||||
// NOTE: lock the Tree first, then lock the _entityMap.
|
||||
|
@ -93,10 +94,10 @@ void EntityTree::eraseNonLocalEntities() {
|
|||
foreach(EntityItemPointer entity, _entityMap) {
|
||||
EntityTreeElementPointer element = entity->getElement();
|
||||
if (element) {
|
||||
element->cleanupNonLocalEntities();
|
||||
element->cleanupDomainAndNonOwnedEntities();
|
||||
}
|
||||
|
||||
if (entity->isLocalEntity()) {
|
||||
if (entity->isLocalEntity() || (entity->isAvatarEntity() && entity->getOwningAvatarID() == getMyAvatarSessionUUID())) {
|
||||
savedEntities[entity->getEntityItemID()] = entity;
|
||||
} else {
|
||||
int32_t spaceIndex = entity->getSpaceIndex();
|
||||
|
@ -114,15 +115,16 @@ void EntityTree::eraseNonLocalEntities() {
|
|||
|
||||
{
|
||||
QWriteLocker locker(&_needsParentFixupLock);
|
||||
QVector<EntityItemWeakPointer> localEntitiesNeedsParentFixup;
|
||||
QVector<EntityItemWeakPointer> needParentFixup;
|
||||
|
||||
foreach (EntityItemWeakPointer entityItem, _needsParentFixup) {
|
||||
if (!entityItem.expired() && entityItem.lock()->isLocalEntity()) {
|
||||
localEntitiesNeedsParentFixup.push_back(entityItem);
|
||||
auto entity = entityItem.lock();
|
||||
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<QSizeF(const QUuid&, const QString&)> EntityTree::_textSizeOperator = nullptr;
|
||||
std::function<bool()> EntityTree::_areEntityClicksCapturedOperator = nullptr;
|
||||
|
||||
QObject* EntityTree::getEntityObject(const QUuid& id) {
|
||||
if (_getEntityObjectOperator) {
|
||||
|
@ -2987,6 +2990,13 @@ QSizeF EntityTree::textSize(const QUuid& id, const QString& text) {
|
|||
return QSizeF(0.0f, 0.0f);
|
||||
}
|
||||
|
||||
bool EntityTree::areEntityClicksCaptured() {
|
||||
if (_areEntityClicksCapturedOperator) {
|
||||
return _areEntityClicksCapturedOperator();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void EntityTree::updateEntityQueryAACubeWorker(SpatiallyNestablePointer object, EntityEditPacketSender* packetSender,
|
||||
MovingEntitiesOperator& moveOperator, bool force, bool tellServer) {
|
||||
// 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 readBitstreamToTree(const unsigned char* bitstream,
|
||||
|
@ -255,6 +255,7 @@ public:
|
|||
QByteArray computeNonce(const QString& certID, const QString ownerKey);
|
||||
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 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 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; }
|
||||
|
||||
void updateEntityQueryAACube(SpatiallyNestablePointer object, EntityEditPacketSender* packetSender,
|
||||
|
@ -378,6 +382,7 @@ private:
|
|||
|
||||
static std::function<QObject*(const QUuid&)> _getEntityObjectOperator;
|
||||
static std::function<QSizeF(const QUuid&, const QString&)> _textSizeOperator;
|
||||
static std::function<bool()> _areEntityClicksCapturedOperator;
|
||||
|
||||
std::vector<int32_t> _staleProxies;
|
||||
|
||||
|
|
|
@ -697,11 +697,11 @@ EntityItemPointer EntityTreeElement::getEntityWithEntityItemID(const EntityItemI
|
|||
return foundEntity;
|
||||
}
|
||||
|
||||
void EntityTreeElement::cleanupNonLocalEntities() {
|
||||
void EntityTreeElement::cleanupDomainAndNonOwnedEntities() {
|
||||
withWriteLock([&] {
|
||||
EntityItems savedEntities;
|
||||
foreach(EntityItemPointer entity, _entityItems) {
|
||||
if (!entity->isLocalEntity()) {
|
||||
if (!(entity->isLocalEntity() || (entity->isAvatarEntity() && entity->getOwningAvatarID() == getTree()->getMyAvatarSessionUUID()))) {
|
||||
entity->preDelete();
|
||||
entity->_element = NULL;
|
||||
} else {
|
||||
|
|
|
@ -190,7 +190,7 @@ public:
|
|||
EntityItemPointer getEntityWithEntityItemID(const EntityItemID& id) const;
|
||||
void getEntitiesInside(const AACube& box, QVector<EntityItemPointer>& foundEntities);
|
||||
|
||||
void cleanupNonLocalEntities();
|
||||
void cleanupDomainAndNonOwnedEntities();
|
||||
void cleanupEntities(); /// called by EntityTree on cleanup this will free all entities
|
||||
bool removeEntityItem(EntityItemPointer entity, bool deletion = false);
|
||||
|
||||
|
|
|
@ -164,7 +164,7 @@ protected:
|
|||
int _lastKnownCurrentFrame{-1};
|
||||
|
||||
glm::u8vec3 _color;
|
||||
glm::vec3 _modelScale;
|
||||
glm::vec3 _modelScale { 1.0f };
|
||||
QString _modelURL;
|
||||
bool _relayParentJoints;
|
||||
bool _groupCulled { false };
|
||||
|
|
|
@ -167,7 +167,6 @@ glm::mat4 getGlobalTransform(const QMultiMap<QString, QString>& _connectionParen
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return globalTransform;
|
||||
}
|
||||
|
||||
|
@ -436,6 +435,8 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr
|
|||
hfmModel.originalURL = url;
|
||||
|
||||
float unitScaleFactor = 1.0f;
|
||||
glm::quat upAxisZRotation;
|
||||
bool applyUpAxisZRotation = false;
|
||||
glm::vec3 ambientColor;
|
||||
QString hifiGlobalNodeID;
|
||||
unsigned int meshIndex = 0;
|
||||
|
@ -473,11 +474,22 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr
|
|||
if (subobject.name == propertyName) {
|
||||
static const QVariant UNIT_SCALE_FACTOR = QByteArray("UnitScaleFactor");
|
||||
static const QVariant AMBIENT_COLOR = QByteArray("AmbientColor");
|
||||
static const QVariant UP_AXIS = QByteArray("UpAxis");
|
||||
const auto& subpropName = subobject.properties.at(0);
|
||||
if (subpropName == UNIT_SCALE_FACTOR) {
|
||||
unitScaleFactor = subobject.properties.at(index).toFloat();
|
||||
} else if (subpropName == AMBIENT_COLOR) {
|
||||
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.isSkeletonJoint = fbxModel.isLimbNode;
|
||||
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;
|
||||
|
||||
if (joint.parentIndex == -1) {
|
||||
joint.transform = hfmModel.offset * glm::translate(joint.translation) * joint.preTransform *
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -149,7 +149,7 @@ public:
|
|||
|
||||
OctreeElementPointer getRoot() { return _rootElement; }
|
||||
|
||||
virtual void eraseNonLocalEntities() { _isDirty = true; };
|
||||
virtual void eraseDomainAndNonOwnedEntities() { _isDirty = true; };
|
||||
virtual void eraseAllOctreeElements(bool createNewRoot = true);
|
||||
|
||||
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) {
|
||||
_tree->withWriteLock([&] {
|
||||
_tree->eraseNonLocalEntities();
|
||||
_tree->eraseDomainAndNonOwnedEntities();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ public:
|
|||
virtual void init();
|
||||
|
||||
/// clears the tree
|
||||
virtual void clearNonLocalEntities();
|
||||
virtual void clearDomainAndNonOwnedEntities();
|
||||
virtual void clear();
|
||||
|
||||
float getAverageElementsPerPacket() const { return _elementsPerPacket.getAverage(); }
|
||||
|
|
|
@ -1346,14 +1346,19 @@ void Model::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
|||
}
|
||||
|
||||
void Model::computeMeshPartLocalBounds() {
|
||||
for (auto& part : _modelMeshRenderItems) {
|
||||
const Model::MeshState& state = _meshStates.at(part->_meshIndex);
|
||||
if (_useDualQuaternionSkinning) {
|
||||
part->computeAdjustedLocalBound(state.clusterDualQuaternions);
|
||||
} else {
|
||||
part->computeAdjustedLocalBound(state.clusterMatrices);
|
||||
}
|
||||
render::Transaction transaction;
|
||||
auto meshStates = _meshStates;
|
||||
for (auto renderItem : _modelMeshRenderItemIDs) {
|
||||
transaction.updateItem<ModelMeshPartPayload>(renderItem, [this, meshStates](ModelMeshPartPayload& data) {
|
||||
const Model::MeshState& state = meshStates.at(data._meshIndex);
|
||||
if (_useDualQuaternionSkinning) {
|
||||
data.computeAdjustedLocalBound(state.clusterDualQuaternions);
|
||||
} else {
|
||||
data.computeAdjustedLocalBound(state.clusterMatrices);
|
||||
}
|
||||
});
|
||||
}
|
||||
AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction);
|
||||
}
|
||||
|
||||
// virtual
|
||||
|
|
|
@ -976,7 +976,9 @@ void ScriptEngine::addEventHandler(const EntityItemID& entityID, const QString&
|
|||
using PointerHandler = std::function<void(const EntityItemID&, const PointerEvent&)>;
|
||||
auto makePointerHandler = [this](QString eventName) -> PointerHandler {
|
||||
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) });
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue