mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 18:13:05 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into loginInitiative2
This commit is contained in:
commit
e32460ed96
37 changed files with 495 additions and 191 deletions
Binary file not shown.
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 164 KiB |
Binary file not shown.
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 175 KiB |
|
@ -39,6 +39,7 @@ Item {
|
||||||
property string sendingPubliclyEffectImage;
|
property string sendingPubliclyEffectImage;
|
||||||
property var http;
|
property var http;
|
||||||
property var listModelName;
|
property var listModelName;
|
||||||
|
property var keyboardContainer: nil;
|
||||||
|
|
||||||
// This object is always used in a popup or full-screen Wallet section.
|
// This object is always used in a popup or full-screen Wallet section.
|
||||||
// This MouseArea is used to prevent a user from being
|
// This MouseArea is used to prevent a user from being
|
||||||
|
@ -1125,8 +1126,7 @@ Item {
|
||||||
checked: Settings.getValue("sendAssetsNearbyPublicly", true);
|
checked: Settings.getValue("sendAssetsNearbyPublicly", true);
|
||||||
text: "Show Effect"
|
text: "Show Effect"
|
||||||
// Anchors
|
// Anchors
|
||||||
anchors.top: messageContainer.bottom;
|
anchors.verticalCenter: bottomBarContainer.verticalCenter;
|
||||||
anchors.topMargin: 16;
|
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.leftMargin: 20;
|
anchors.leftMargin: 20;
|
||||||
width: 130;
|
width: 130;
|
||||||
|
@ -1168,6 +1168,9 @@ Item {
|
||||||
lightboxPopup.visible = false;
|
lightboxPopup.visible = false;
|
||||||
}
|
}
|
||||||
lightboxPopup.visible = true;
|
lightboxPopup.visible = true;
|
||||||
|
if (keyboardContainer) {
|
||||||
|
keyboardContainer.keyboardRaised = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1178,8 +1181,8 @@ Item {
|
||||||
anchors.leftMargin: 20;
|
anchors.leftMargin: 20;
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
anchors.rightMargin: 20;
|
anchors.rightMargin: 20;
|
||||||
anchors.bottom: parent.bottom;
|
anchors.top: messageContainer.bottom;
|
||||||
anchors.bottomMargin: 20;
|
anchors.topMargin: 20;
|
||||||
height: 60;
|
height: 60;
|
||||||
|
|
||||||
// "CANCEL" button
|
// "CANCEL" button
|
||||||
|
@ -1187,11 +1190,11 @@ Item {
|
||||||
id: cancelButton_sendAssetStep;
|
id: cancelButton_sendAssetStep;
|
||||||
color: root.assetName === "" ? hifi.buttons.noneBorderlessWhite : hifi.buttons.noneBorderlessGray;
|
color: root.assetName === "" ? hifi.buttons.noneBorderlessWhite : hifi.buttons.noneBorderlessGray;
|
||||||
colorScheme: hifi.colorSchemes.dark;
|
colorScheme: hifi.colorSchemes.dark;
|
||||||
anchors.left: parent.left;
|
anchors.right: sendButton.left;
|
||||||
anchors.leftMargin: 24;
|
anchors.rightMargin: 24;
|
||||||
anchors.verticalCenter: parent.verticalCenter;
|
anchors.verticalCenter: parent.verticalCenter;
|
||||||
height: 40;
|
height: 40;
|
||||||
width: 150;
|
width: 100;
|
||||||
text: "CANCEL";
|
text: "CANCEL";
|
||||||
onClicked: {
|
onClicked: {
|
||||||
resetSendAssetData();
|
resetSendAssetData();
|
||||||
|
@ -1205,10 +1208,10 @@ Item {
|
||||||
color: hifi.buttons.blue;
|
color: hifi.buttons.blue;
|
||||||
colorScheme: root.assetName === "" ? hifi.colorSchemes.dark : hifi.colorSchemes.light;
|
colorScheme: root.assetName === "" ? hifi.colorSchemes.dark : hifi.colorSchemes.light;
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
anchors.rightMargin: 24;
|
anchors.rightMargin: 0;
|
||||||
anchors.verticalCenter: parent.verticalCenter;
|
anchors.verticalCenter: parent.verticalCenter;
|
||||||
height: 40;
|
height: 40;
|
||||||
width: 150;
|
width: 100;
|
||||||
text: "SUBMIT";
|
text: "SUBMIT";
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (root.assetName === "" && parseInt(amountTextField.text) > parseInt(balanceText.text)) {
|
if (root.assetName === "" && parseInt(amountTextField.text) > parseInt(balanceText.text)) {
|
||||||
|
|
|
@ -158,6 +158,7 @@ Rectangle {
|
||||||
listModelName: "Gift Connections";
|
listModelName: "Gift Connections";
|
||||||
z: 998;
|
z: 998;
|
||||||
visible: root.activeView === "giftAsset";
|
visible: root.activeView === "giftAsset";
|
||||||
|
keyboardContainer: root;
|
||||||
anchors.fill: parent;
|
anchors.fill: parent;
|
||||||
parentAppTitleBarHeight: 70;
|
parentAppTitleBarHeight: 70;
|
||||||
parentAppNavBarHeight: 0;
|
parentAppNavBarHeight: 0;
|
||||||
|
@ -585,7 +586,7 @@ Rectangle {
|
||||||
visible: purchasesModel.count !== 0;
|
visible: purchasesModel.count !== 0;
|
||||||
clip: true;
|
clip: true;
|
||||||
model: purchasesModel;
|
model: purchasesModel;
|
||||||
snapMode: ListView.SnapToItem;
|
snapMode: ListView.NoSnap;
|
||||||
// Anchors
|
// Anchors
|
||||||
anchors.top: separator.bottom;
|
anchors.top: separator.bottom;
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
|
|
|
@ -354,6 +354,7 @@ Rectangle {
|
||||||
listModelName: "Send Money Connections";
|
listModelName: "Send Money Connections";
|
||||||
z: 997;
|
z: 997;
|
||||||
visible: root.activeView === "sendMoney";
|
visible: root.activeView === "sendMoney";
|
||||||
|
keyboardContainer: root;
|
||||||
anchors.fill: parent;
|
anchors.fill: parent;
|
||||||
parentAppTitleBarHeight: titleBarContainer.height;
|
parentAppTitleBarHeight: titleBarContainer.height;
|
||||||
parentAppNavBarHeight: tabButtonsContainer.height;
|
parentAppNavBarHeight: tabButtonsContainer.height;
|
||||||
|
|
|
@ -8558,6 +8558,16 @@ QUuid Application::getTabletFrameID() const {
|
||||||
return HMD->getCurrentTabletFrameID();
|
return HMD->getCurrentTabletFrameID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVector<QUuid> Application::getTabletIDs() const {
|
||||||
|
// Most important overlays first.
|
||||||
|
QVector<QUuid> result;
|
||||||
|
auto HMD = DependencyManager::get<HMDScriptingInterface>();
|
||||||
|
result << HMD->getCurrentTabletScreenID();
|
||||||
|
result << HMD->getCurrentHomeButtonID();
|
||||||
|
result << HMD->getCurrentTabletFrameID();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void Application::setAvatarOverrideUrl(const QUrl& url, bool save) {
|
void Application::setAvatarOverrideUrl(const QUrl& url, bool save) {
|
||||||
_avatarOverrideUrl = url;
|
_avatarOverrideUrl = url;
|
||||||
_saveAvatarOverrideUrl = save;
|
_saveAvatarOverrideUrl = save;
|
||||||
|
|
|
@ -299,6 +299,7 @@ public:
|
||||||
OverlayID getTabletScreenID() const;
|
OverlayID getTabletScreenID() const;
|
||||||
OverlayID getTabletHomeButtonID() const;
|
OverlayID getTabletHomeButtonID() const;
|
||||||
QUuid getTabletFrameID() const; // may be an entity or an overlay
|
QUuid getTabletFrameID() const; // may be an entity or an overlay
|
||||||
|
QVector<QUuid> getTabletIDs() const; // In order of most important IDs first.
|
||||||
|
|
||||||
void setAvatarOverrideUrl(const QUrl& url, bool save);
|
void setAvatarOverrideUrl(const QUrl& url, bool save);
|
||||||
void clearAvatarOverrideUrl() { _avatarOverrideUrl = QUrl(); _saveAvatarOverrideUrl = false; }
|
void clearAvatarOverrideUrl() { _avatarOverrideUrl = QUrl(); _saveAvatarOverrideUrl = false; }
|
||||||
|
|
|
@ -108,6 +108,9 @@ AvatarBookmarks::AvatarBookmarks() {
|
||||||
|
|
||||||
if (!QFile::copy(defaultBookmarksFilename, _bookmarksFilename)) {
|
if (!QFile::copy(defaultBookmarksFilename, _bookmarksFilename)) {
|
||||||
qDebug() << "failed to copy" << defaultBookmarksFilename << "to" << _bookmarksFilename;
|
qDebug() << "failed to copy" << defaultBookmarksFilename << "to" << _bookmarksFilename;
|
||||||
|
} else {
|
||||||
|
QFile bookmarksFile(_bookmarksFilename);
|
||||||
|
bookmarksFile.setPermissions(bookmarksFile.permissions() | QFile::WriteUser);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
readFromFile();
|
readFromFile();
|
||||||
|
|
|
@ -629,8 +629,6 @@ public:
|
||||||
|
|
||||||
const MyHead* getMyHead() const;
|
const MyHead* getMyHead() const;
|
||||||
|
|
||||||
Q_INVOKABLE void toggleSmoothPoleVectors() { _skeletonModel->getRig().toggleSmoothPoleVectors(); };
|
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Get the current position of the avatar's "Head" joint.
|
* Get the current position of the avatar's "Head" joint.
|
||||||
* @function MyAvatar.getHeadPosition
|
* @function MyAvatar.getHeadPosition
|
||||||
|
|
|
@ -46,7 +46,7 @@ static AnimPose computeHipsInSensorFrame(MyAvatar* myAvatar, bool isFlying) {
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::mat4 hipsMat;
|
glm::mat4 hipsMat;
|
||||||
if (myAvatar->getCenterOfGravityModelEnabled() && !isFlying && !(myAvatar->getIsInWalkingState())) {
|
if (myAvatar->getCenterOfGravityModelEnabled() && !isFlying && !(myAvatar->getIsInWalkingState()) && myAvatar->getHMDLeanRecenterEnabled()) {
|
||||||
// then we use center of gravity model
|
// then we use center of gravity model
|
||||||
hipsMat = myAvatar->deriveBodyUsingCgModel();
|
hipsMat = myAvatar->deriveBodyUsingCgModel();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -532,6 +532,8 @@ RayToOverlayIntersectionResult Overlays::findRayIntersectionVector(const PickRay
|
||||||
bool visibleOnly, bool collidableOnly) {
|
bool visibleOnly, bool collidableOnly) {
|
||||||
float bestDistance = std::numeric_limits<float>::max();
|
float bestDistance = std::numeric_limits<float>::max();
|
||||||
bool bestIsFront = false;
|
bool bestIsFront = false;
|
||||||
|
bool bestIsTablet = false;
|
||||||
|
auto tabletIDs = qApp->getTabletIDs();
|
||||||
|
|
||||||
QMutexLocker locker(&_mutex);
|
QMutexLocker locker(&_mutex);
|
||||||
RayToOverlayIntersectionResult result;
|
RayToOverlayIntersectionResult result;
|
||||||
|
@ -554,10 +556,11 @@ RayToOverlayIntersectionResult Overlays::findRayIntersectionVector(const PickRay
|
||||||
if (thisOverlay->findRayIntersectionExtraInfo(ray.origin, ray.direction, thisDistance,
|
if (thisOverlay->findRayIntersectionExtraInfo(ray.origin, ray.direction, thisDistance,
|
||||||
thisFace, thisSurfaceNormal, thisExtraInfo, precisionPicking)) {
|
thisFace, thisSurfaceNormal, thisExtraInfo, precisionPicking)) {
|
||||||
bool isDrawInFront = thisOverlay->getDrawInFront();
|
bool isDrawInFront = thisOverlay->getDrawInFront();
|
||||||
if ((bestIsFront && isDrawInFront && thisDistance < bestDistance)
|
bool isTablet = tabletIDs.contains(thisID);
|
||||||
|| (!bestIsFront && (isDrawInFront || thisDistance < bestDistance))) {
|
if ((isDrawInFront && !bestIsFront && !bestIsTablet)
|
||||||
|
|| ((isTablet || isDrawInFront || !bestIsFront) && thisDistance < bestDistance)) {
|
||||||
bestIsFront = isDrawInFront;
|
bestIsFront = isDrawInFront;
|
||||||
|
bestIsTablet = isTablet;
|
||||||
bestDistance = thisDistance;
|
bestDistance = thisDistance;
|
||||||
result.intersects = true;
|
result.intersects = true;
|
||||||
result.distance = thisDistance;
|
result.distance = thisDistance;
|
||||||
|
@ -828,40 +831,12 @@ PointerEvent Overlays::calculateOverlayPointerEvent(OverlayID overlayID, PickRay
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RayToOverlayIntersectionResult Overlays::findRayIntersectionForMouseEvent(PickRay ray) {
|
|
||||||
QVector<OverlayID> overlaysToInclude;
|
|
||||||
QVector<OverlayID> overlaysToDiscard;
|
|
||||||
RayToOverlayIntersectionResult rayPickResult;
|
|
||||||
|
|
||||||
// first priority is tablet screen
|
|
||||||
overlaysToInclude << qApp->getTabletScreenID();
|
|
||||||
rayPickResult = findRayIntersectionVector(ray, true, overlaysToInclude, overlaysToDiscard);
|
|
||||||
if (rayPickResult.intersects) {
|
|
||||||
return rayPickResult;
|
|
||||||
}
|
|
||||||
// then tablet home button
|
|
||||||
overlaysToInclude.clear();
|
|
||||||
overlaysToInclude << qApp->getTabletHomeButtonID();
|
|
||||||
rayPickResult = findRayIntersectionVector(ray, true, overlaysToInclude, overlaysToDiscard);
|
|
||||||
if (rayPickResult.intersects) {
|
|
||||||
return rayPickResult;
|
|
||||||
}
|
|
||||||
// then tablet frame
|
|
||||||
overlaysToInclude.clear();
|
|
||||||
overlaysToInclude << OverlayID(qApp->getTabletFrameID());
|
|
||||||
rayPickResult = findRayIntersectionVector(ray, true, overlaysToInclude, overlaysToDiscard);
|
|
||||||
if (rayPickResult.intersects) {
|
|
||||||
return rayPickResult;
|
|
||||||
}
|
|
||||||
// then whatever
|
|
||||||
return findRayIntersection(ray);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Overlays::mousePressEvent(QMouseEvent* event) {
|
bool Overlays::mousePressEvent(QMouseEvent* event) {
|
||||||
PerformanceTimer perfTimer("Overlays::mousePressEvent");
|
PerformanceTimer perfTimer("Overlays::mousePressEvent");
|
||||||
|
|
||||||
PickRay ray = qApp->computePickRay(event->x(), event->y());
|
PickRay ray = qApp->computePickRay(event->x(), event->y());
|
||||||
RayToOverlayIntersectionResult rayPickResult = findRayIntersectionForMouseEvent(ray);
|
RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector<OverlayID>(),
|
||||||
|
QVector<OverlayID>());
|
||||||
if (rayPickResult.intersects) {
|
if (rayPickResult.intersects) {
|
||||||
_currentClickingOnOverlayID = rayPickResult.overlayID;
|
_currentClickingOnOverlayID = rayPickResult.overlayID;
|
||||||
|
|
||||||
|
@ -901,7 +876,8 @@ bool Overlays::mouseDoublePressEvent(QMouseEvent* event) {
|
||||||
PerformanceTimer perfTimer("Overlays::mouseDoublePressEvent");
|
PerformanceTimer perfTimer("Overlays::mouseDoublePressEvent");
|
||||||
|
|
||||||
PickRay ray = qApp->computePickRay(event->x(), event->y());
|
PickRay ray = qApp->computePickRay(event->x(), event->y());
|
||||||
RayToOverlayIntersectionResult rayPickResult = findRayIntersectionForMouseEvent(ray);
|
RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector<OverlayID>(),
|
||||||
|
QVector<OverlayID>());
|
||||||
if (rayPickResult.intersects) {
|
if (rayPickResult.intersects) {
|
||||||
_currentClickingOnOverlayID = rayPickResult.overlayID;
|
_currentClickingOnOverlayID = rayPickResult.overlayID;
|
||||||
|
|
||||||
|
@ -964,7 +940,8 @@ bool Overlays::mouseReleaseEvent(QMouseEvent* event) {
|
||||||
PerformanceTimer perfTimer("Overlays::mouseReleaseEvent");
|
PerformanceTimer perfTimer("Overlays::mouseReleaseEvent");
|
||||||
|
|
||||||
PickRay ray = qApp->computePickRay(event->x(), event->y());
|
PickRay ray = qApp->computePickRay(event->x(), event->y());
|
||||||
RayToOverlayIntersectionResult rayPickResult = findRayIntersectionForMouseEvent(ray);
|
RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector<OverlayID>(),
|
||||||
|
QVector<OverlayID>());
|
||||||
if (rayPickResult.intersects) {
|
if (rayPickResult.intersects) {
|
||||||
auto pointerEvent = calculateOverlayPointerEvent(rayPickResult.overlayID, ray, rayPickResult, event, PointerEvent::Release);
|
auto pointerEvent = calculateOverlayPointerEvent(rayPickResult.overlayID, ray, rayPickResult, event, PointerEvent::Release);
|
||||||
mouseReleasePointerEvent(rayPickResult.overlayID, pointerEvent);
|
mouseReleasePointerEvent(rayPickResult.overlayID, pointerEvent);
|
||||||
|
@ -993,7 +970,8 @@ bool Overlays::mouseMoveEvent(QMouseEvent* event) {
|
||||||
PerformanceTimer perfTimer("Overlays::mouseMoveEvent");
|
PerformanceTimer perfTimer("Overlays::mouseMoveEvent");
|
||||||
|
|
||||||
PickRay ray = qApp->computePickRay(event->x(), event->y());
|
PickRay ray = qApp->computePickRay(event->x(), event->y());
|
||||||
RayToOverlayIntersectionResult rayPickResult = findRayIntersectionForMouseEvent(ray);
|
RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector<OverlayID>(),
|
||||||
|
QVector<OverlayID>());
|
||||||
if (rayPickResult.intersects) {
|
if (rayPickResult.intersects) {
|
||||||
auto pointerEvent = calculateOverlayPointerEvent(rayPickResult.overlayID, ray, rayPickResult, event, PointerEvent::Move);
|
auto pointerEvent = calculateOverlayPointerEvent(rayPickResult.overlayID, ray, rayPickResult, event, PointerEvent::Move);
|
||||||
mouseMovePointerEvent(rayPickResult.overlayID, pointerEvent);
|
mouseMovePointerEvent(rayPickResult.overlayID, pointerEvent);
|
||||||
|
|
|
@ -44,8 +44,7 @@ void OverlayPropertyResultFromScriptValue(const QScriptValue& object, OverlayPro
|
||||||
const OverlayID UNKNOWN_OVERLAY_ID = OverlayID();
|
const OverlayID UNKNOWN_OVERLAY_ID = OverlayID();
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* The result of a {@link PickRay} search using {@link Overlays.findRayIntersection|findRayIntersection} or
|
* The result of a {@link PickRay} search using {@link Overlays.findRayIntersection|findRayIntersection}.
|
||||||
* {@link Overlays.findRayIntersectionVector|findRayIntersectionVector}.
|
|
||||||
* @typedef {object} Overlays.RayToOverlayIntersectionResult
|
* @typedef {object} Overlays.RayToOverlayIntersectionResult
|
||||||
* @property {boolean} intersects - <code>true</code> if the {@link PickRay} intersected with a 3D overlay, otherwise
|
* @property {boolean} intersects - <code>true</code> if the {@link PickRay} intersected with a 3D overlay, otherwise
|
||||||
* <code>false</code>.
|
* <code>false</code>.
|
||||||
|
@ -383,7 +382,11 @@ public slots:
|
||||||
OverlayPropertyResult getOverlaysProperties(const QVariant& overlaysProperties);
|
OverlayPropertyResult getOverlaysProperties(const QVariant& overlaysProperties);
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Find the closest 3D overlay intersected by a {@link PickRay}.
|
* Find the closest 3D overlay intersected by a {@link PickRay}. Overlays with their <code>drawInFront</code> property set
|
||||||
|
* to <code>true</code> have priority over overlays that don't, except that tablet overlays have priority over any
|
||||||
|
* <code>drawInFront</code> overlays behind them. I.e., if a <code>drawInFront</code> overlay is behind one that isn't
|
||||||
|
* <code>drawInFront</code>, the <code>drawInFront</code> overlay is returned, but if a tablet overlay is in front of a
|
||||||
|
* <code>drawInFront</code> overlay, the tablet overlay is returned.
|
||||||
* @function Overlays.findRayIntersection
|
* @function Overlays.findRayIntersection
|
||||||
* @param {PickRay} pickRay - The PickRay to use for finding overlays.
|
* @param {PickRay} pickRay - The PickRay to use for finding overlays.
|
||||||
* @param {boolean} [precisionPicking=false] - <em>Unused</em>; exists to match Entity API.
|
* @param {boolean} [precisionPicking=false] - <em>Unused</em>; exists to match Entity API.
|
||||||
|
@ -750,8 +753,6 @@ private:
|
||||||
OverlayID _currentClickingOnOverlayID { UNKNOWN_OVERLAY_ID };
|
OverlayID _currentClickingOnOverlayID { UNKNOWN_OVERLAY_ID };
|
||||||
OverlayID _currentHoverOverOverlayID { UNKNOWN_OVERLAY_ID };
|
OverlayID _currentHoverOverOverlayID { UNKNOWN_OVERLAY_ID };
|
||||||
|
|
||||||
RayToOverlayIntersectionResult findRayIntersectionForMouseEvent(PickRay ray);
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void mousePressPointerEvent(const OverlayID& overlayID, const PointerEvent& event);
|
void mousePressPointerEvent(const OverlayID& overlayID, const PointerEvent& event);
|
||||||
void mouseMovePointerEvent(const OverlayID& overlayID, const PointerEvent& event);
|
void mouseMovePointerEvent(const OverlayID& overlayID, const PointerEvent& event);
|
||||||
|
|
|
@ -1253,7 +1253,6 @@ void Rig::updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnab
|
||||||
const glm::mat4& rigToSensorMatrix, const glm::mat4& sensorToRigMatrix) {
|
const glm::mat4& rigToSensorMatrix, const glm::mat4& sensorToRigMatrix) {
|
||||||
|
|
||||||
const bool ENABLE_POLE_VECTORS = true;
|
const bool ENABLE_POLE_VECTORS = true;
|
||||||
const float ELBOW_POLE_VECTOR_BLEND_FACTOR = 0.95f;
|
|
||||||
|
|
||||||
if (leftHandEnabled) {
|
if (leftHandEnabled) {
|
||||||
|
|
||||||
|
@ -1279,33 +1278,16 @@ void Rig::updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnab
|
||||||
bool usePoleVector = calculateElbowPoleVector(handJointIndex, elbowJointIndex, armJointIndex, oppositeArmJointIndex, poleVector);
|
bool usePoleVector = calculateElbowPoleVector(handJointIndex, elbowJointIndex, armJointIndex, oppositeArmJointIndex, poleVector);
|
||||||
if (usePoleVector) {
|
if (usePoleVector) {
|
||||||
glm::vec3 sensorPoleVector = transformVectorFast(rigToSensorMatrix, poleVector);
|
glm::vec3 sensorPoleVector = transformVectorFast(rigToSensorMatrix, poleVector);
|
||||||
|
|
||||||
if (_smoothPoleVectors) {
|
|
||||||
// smooth toward desired pole vector from previous pole vector... to reduce jitter
|
|
||||||
if (!_prevLeftHandPoleVectorValid) {
|
|
||||||
_prevLeftHandPoleVectorValid = true;
|
|
||||||
_prevLeftHandPoleVector = sensorPoleVector;
|
|
||||||
}
|
|
||||||
glm::quat deltaRot = rotationBetween(_prevLeftHandPoleVector, sensorPoleVector);
|
|
||||||
glm::quat smoothDeltaRot = safeMix(deltaRot, Quaternions::IDENTITY, ELBOW_POLE_VECTOR_BLEND_FACTOR);
|
|
||||||
_prevLeftHandPoleVector = smoothDeltaRot * _prevLeftHandPoleVector;
|
|
||||||
} else {
|
|
||||||
_prevLeftHandPoleVector = sensorPoleVector;
|
|
||||||
}
|
|
||||||
_animVars.set("leftHandPoleVectorEnabled", true);
|
_animVars.set("leftHandPoleVectorEnabled", true);
|
||||||
_animVars.set("leftHandPoleReferenceVector", Vectors::UNIT_X);
|
_animVars.set("leftHandPoleReferenceVector", Vectors::UNIT_X);
|
||||||
_animVars.set("leftHandPoleVector", transformVectorFast(sensorToRigMatrix, _prevLeftHandPoleVector));
|
_animVars.set("leftHandPoleVector", transformVectorFast(sensorToRigMatrix, sensorPoleVector));
|
||||||
} else {
|
} else {
|
||||||
_prevLeftHandPoleVectorValid = false;
|
|
||||||
_animVars.set("leftHandPoleVectorEnabled", false);
|
_animVars.set("leftHandPoleVectorEnabled", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
_prevLeftHandPoleVectorValid = false;
|
|
||||||
_animVars.set("leftHandPoleVectorEnabled", false);
|
_animVars.set("leftHandPoleVectorEnabled", false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_prevLeftHandPoleVectorValid = false;
|
|
||||||
_animVars.set("leftHandPoleVectorEnabled", false);
|
_animVars.set("leftHandPoleVectorEnabled", false);
|
||||||
|
|
||||||
_animVars.unset("leftHandPosition");
|
_animVars.unset("leftHandPosition");
|
||||||
|
@ -1344,33 +1326,16 @@ void Rig::updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnab
|
||||||
bool usePoleVector = calculateElbowPoleVector(handJointIndex, elbowJointIndex, armJointIndex, oppositeArmJointIndex, poleVector);
|
bool usePoleVector = calculateElbowPoleVector(handJointIndex, elbowJointIndex, armJointIndex, oppositeArmJointIndex, poleVector);
|
||||||
if (usePoleVector) {
|
if (usePoleVector) {
|
||||||
glm::vec3 sensorPoleVector = transformVectorFast(rigToSensorMatrix, poleVector);
|
glm::vec3 sensorPoleVector = transformVectorFast(rigToSensorMatrix, poleVector);
|
||||||
|
|
||||||
if (_smoothPoleVectors) {
|
|
||||||
// smooth toward desired pole vector from previous pole vector... to reduce jitter
|
|
||||||
if (!_prevRightHandPoleVectorValid) {
|
|
||||||
_prevRightHandPoleVectorValid = true;
|
|
||||||
_prevRightHandPoleVector = sensorPoleVector;
|
|
||||||
}
|
|
||||||
glm::quat deltaRot = rotationBetween(_prevRightHandPoleVector, sensorPoleVector);
|
|
||||||
glm::quat smoothDeltaRot = safeMix(deltaRot, Quaternions::IDENTITY, ELBOW_POLE_VECTOR_BLEND_FACTOR);
|
|
||||||
_prevRightHandPoleVector = smoothDeltaRot * _prevRightHandPoleVector;
|
|
||||||
} else {
|
|
||||||
_prevRightHandPoleVector = sensorPoleVector;
|
|
||||||
}
|
|
||||||
|
|
||||||
_animVars.set("rightHandPoleVectorEnabled", true);
|
_animVars.set("rightHandPoleVectorEnabled", true);
|
||||||
_animVars.set("rightHandPoleReferenceVector", -Vectors::UNIT_X);
|
_animVars.set("rightHandPoleReferenceVector", -Vectors::UNIT_X);
|
||||||
_animVars.set("rightHandPoleVector", transformVectorFast(sensorToRigMatrix, _prevRightHandPoleVector));
|
_animVars.set("rightHandPoleVector", transformVectorFast(sensorToRigMatrix, sensorPoleVector));
|
||||||
} else {
|
} else {
|
||||||
_prevRightHandPoleVectorValid = false;
|
|
||||||
_animVars.set("rightHandPoleVectorEnabled", false);
|
_animVars.set("rightHandPoleVectorEnabled", false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_prevRightHandPoleVectorValid = false;
|
|
||||||
_animVars.set("rightHandPoleVectorEnabled", false);
|
_animVars.set("rightHandPoleVectorEnabled", false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_prevRightHandPoleVectorValid = false;
|
|
||||||
_animVars.set("rightHandPoleVectorEnabled", false);
|
_animVars.set("rightHandPoleVectorEnabled", false);
|
||||||
|
|
||||||
_animVars.unset("rightHandPosition");
|
_animVars.unset("rightHandPosition");
|
||||||
|
|
|
@ -227,7 +227,6 @@ public:
|
||||||
const AnimVariantMap& getAnimVars() const { return _lastAnimVars; }
|
const AnimVariantMap& getAnimVars() const { return _lastAnimVars; }
|
||||||
const AnimContext::DebugStateMachineMap& getStateMachineMap() const { return _lastContext.getStateMachineMap(); }
|
const AnimContext::DebugStateMachineMap& getStateMachineMap() const { return _lastContext.getStateMachineMap(); }
|
||||||
|
|
||||||
void toggleSmoothPoleVectors() { _smoothPoleVectors = !_smoothPoleVectors; };
|
|
||||||
signals:
|
signals:
|
||||||
void onLoadComplete();
|
void onLoadComplete();
|
||||||
|
|
||||||
|
@ -381,14 +380,6 @@ protected:
|
||||||
glm::vec3 _prevLeftFootPoleVector { Vectors::UNIT_Z }; // sensor space
|
glm::vec3 _prevLeftFootPoleVector { Vectors::UNIT_Z }; // sensor space
|
||||||
bool _prevLeftFootPoleVectorValid { false };
|
bool _prevLeftFootPoleVectorValid { false };
|
||||||
|
|
||||||
glm::vec3 _prevRightHandPoleVector{ -Vectors::UNIT_Z }; // sensor space
|
|
||||||
bool _prevRightHandPoleVectorValid{ false };
|
|
||||||
|
|
||||||
glm::vec3 _prevLeftHandPoleVector{ -Vectors::UNIT_Z }; // sensor space
|
|
||||||
bool _prevLeftHandPoleVectorValid{ false };
|
|
||||||
|
|
||||||
bool _smoothPoleVectors { false };
|
|
||||||
|
|
||||||
int _rigId;
|
int _rigId;
|
||||||
bool _headEnabled { false };
|
bool _headEnabled { false };
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,7 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] =
|
||||||
(&::gpu::gl::GLBackend::do_clearFramebuffer),
|
(&::gpu::gl::GLBackend::do_clearFramebuffer),
|
||||||
(&::gpu::gl::GLBackend::do_blit),
|
(&::gpu::gl::GLBackend::do_blit),
|
||||||
(&::gpu::gl::GLBackend::do_generateTextureMips),
|
(&::gpu::gl::GLBackend::do_generateTextureMips),
|
||||||
|
(&::gpu::gl::GLBackend::do_generateTextureMipsWithPipeline),
|
||||||
|
|
||||||
(&::gpu::gl::GLBackend::do_advance),
|
(&::gpu::gl::GLBackend::do_advance),
|
||||||
|
|
||||||
|
@ -166,6 +167,10 @@ GLBackend::GLBackend() {
|
||||||
GLBackend::~GLBackend() {}
|
GLBackend::~GLBackend() {}
|
||||||
|
|
||||||
void GLBackend::shutdown() {
|
void GLBackend::shutdown() {
|
||||||
|
if (_mipGenerationFramebufferId) {
|
||||||
|
glDeleteFramebuffers(1, &_mipGenerationFramebufferId);
|
||||||
|
_mipGenerationFramebufferId = 0;
|
||||||
|
}
|
||||||
killInput();
|
killInput();
|
||||||
killTransform();
|
killTransform();
|
||||||
killTextureManagementStage();
|
killTextureManagementStage();
|
||||||
|
|
|
@ -288,6 +288,7 @@ public:
|
||||||
virtual void do_setIndexBuffer(const Batch& batch, size_t paramOffset) final;
|
virtual void do_setIndexBuffer(const Batch& batch, size_t paramOffset) final;
|
||||||
virtual void do_setIndirectBuffer(const Batch& batch, size_t paramOffset) final;
|
virtual void do_setIndirectBuffer(const Batch& batch, size_t paramOffset) final;
|
||||||
virtual void do_generateTextureMips(const Batch& batch, size_t paramOffset) final;
|
virtual void do_generateTextureMips(const Batch& batch, size_t paramOffset) final;
|
||||||
|
virtual void do_generateTextureMipsWithPipeline(const Batch& batch, size_t paramOffset) final;
|
||||||
|
|
||||||
// Transform Stage
|
// Transform Stage
|
||||||
virtual void do_setModelTransform(const Batch& batch, size_t paramOffset) final;
|
virtual void do_setModelTransform(const Batch& batch, size_t paramOffset) final;
|
||||||
|
@ -407,6 +408,8 @@ public:
|
||||||
protected:
|
protected:
|
||||||
virtual GLint getRealUniformLocation(GLint location) const;
|
virtual GLint getRealUniformLocation(GLint location) const;
|
||||||
|
|
||||||
|
virtual void draw(GLenum mode, uint32 numVertices, uint32 startVertex) = 0;
|
||||||
|
|
||||||
void recycle() const override;
|
void recycle() const override;
|
||||||
|
|
||||||
// FIXME instead of a single flag, create a features struct similar to
|
// FIXME instead of a single flag, create a features struct similar to
|
||||||
|
@ -696,6 +699,8 @@ protected:
|
||||||
virtual void initTextureManagementStage();
|
virtual void initTextureManagementStage();
|
||||||
virtual void killTextureManagementStage();
|
virtual void killTextureManagementStage();
|
||||||
|
|
||||||
|
GLuint _mipGenerationFramebufferId{ 0 };
|
||||||
|
|
||||||
typedef void (GLBackend::*CommandCall)(const Batch&, size_t);
|
typedef void (GLBackend::*CommandCall)(const Batch&, size_t);
|
||||||
static CommandCall _commandCalls[Batch::NUM_COMMANDS];
|
static CommandCall _commandCalls[Batch::NUM_COMMANDS];
|
||||||
friend class GLState;
|
friend class GLState;
|
||||||
|
|
|
@ -79,3 +79,55 @@ void GLBackend::do_generateTextureMips(const Batch& batch, size_t paramOffset) {
|
||||||
|
|
||||||
object->generateMips();
|
object->generateMips();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLBackend::do_generateTextureMipsWithPipeline(const Batch& batch, size_t paramOffset) {
|
||||||
|
TexturePointer resourceTexture = batch._textures.get(batch._params[paramOffset + 0]._uint);
|
||||||
|
if (!resourceTexture) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always make sure the GLObject is in sync
|
||||||
|
GLTexture* object = syncGPUObject(resourceTexture);
|
||||||
|
if (object) {
|
||||||
|
GLuint to = object->_texture;
|
||||||
|
glActiveTexture(GL_TEXTURE0 + gpu::slot::texture::MipCreationInput);
|
||||||
|
glBindTexture(object->_target, to);
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto numMips = batch._params[paramOffset + 1]._int;
|
||||||
|
if (numMips < 0) {
|
||||||
|
numMips = resourceTexture->getNumMips();
|
||||||
|
} else {
|
||||||
|
numMips = std::min(numMips, (int)resourceTexture->getNumMips());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_mipGenerationFramebufferId == 0) {
|
||||||
|
glGenFramebuffers(1, &_mipGenerationFramebufferId);
|
||||||
|
Q_ASSERT(_mipGenerationFramebufferId > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, _mipGenerationFramebufferId);
|
||||||
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
|
||||||
|
|
||||||
|
for (int level = 1; level < numMips; level++) {
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, object->_id, level);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, level - 1);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level - 1);
|
||||||
|
|
||||||
|
const auto mipDimensions = resourceTexture->evalMipDimensions(level);
|
||||||
|
glViewport(0, 0, mipDimensions.x, mipDimensions.y);
|
||||||
|
draw(GL_TRIANGLE_STRIP, 4, 0);
|
||||||
|
}
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, numMips - 1);
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
|
resetOutputStage();
|
||||||
|
// Restore viewport
|
||||||
|
ivec4& vp = _transform._viewport;
|
||||||
|
glViewport(vp.x, vp.y, vp.z, vp.w);
|
||||||
|
}
|
||||||
|
|
|
@ -20,6 +20,29 @@ using namespace gpu::gl41;
|
||||||
|
|
||||||
const std::string GL41Backend::GL41_VERSION { "GL41" };
|
const std::string GL41Backend::GL41_VERSION { "GL41" };
|
||||||
|
|
||||||
|
void GL41Backend::draw(GLenum mode, uint32 numVertices, uint32 startVertex) {
|
||||||
|
if (isStereo()) {
|
||||||
|
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||||
|
glDrawArraysInstanced(mode, startVertex, numVertices, 2);
|
||||||
|
#else
|
||||||
|
setupStereoSide(0);
|
||||||
|
glDrawArrays(mode, startVertex, numVertices);
|
||||||
|
setupStereoSide(1);
|
||||||
|
glDrawArrays(mode, startVertex, numVertices);
|
||||||
|
#endif
|
||||||
|
_stats._DSNumTriangles += 2 * numVertices / 3;
|
||||||
|
_stats._DSNumDrawcalls += 2;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
glDrawArrays(mode, startVertex, numVertices);
|
||||||
|
_stats._DSNumTriangles += numVertices / 3;
|
||||||
|
_stats._DSNumDrawcalls++;
|
||||||
|
}
|
||||||
|
_stats._DSNumAPIDrawcalls++;
|
||||||
|
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
}
|
||||||
|
|
||||||
void GL41Backend::do_draw(const Batch& batch, size_t paramOffset) {
|
void GL41Backend::do_draw(const Batch& batch, size_t paramOffset) {
|
||||||
Primitive primitiveType = (Primitive)batch._params[paramOffset + 2]._uint;
|
Primitive primitiveType = (Primitive)batch._params[paramOffset + 2]._uint;
|
||||||
GLenum mode = gl::PRIMITIVE_TO_GL[primitiveType];
|
GLenum mode = gl::PRIMITIVE_TO_GL[primitiveType];
|
||||||
|
|
|
@ -130,6 +130,9 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
void draw(GLenum mode, uint32 numVertices, uint32 startVertex) override;
|
||||||
|
|
||||||
GLuint getFramebufferID(const FramebufferPointer& framebuffer) override;
|
GLuint getFramebufferID(const FramebufferPointer& framebuffer) override;
|
||||||
GLFramebuffer* syncGPUObject(const Framebuffer& framebuffer) override;
|
GLFramebuffer* syncGPUObject(const Framebuffer& framebuffer) override;
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,30 @@ void GL45Backend::recycle() const {
|
||||||
Parent::recycle();
|
Parent::recycle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GL45Backend::draw(GLenum mode, uint32 numVertices, uint32 startVertex) {
|
||||||
|
if (isStereo()) {
|
||||||
|
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||||
|
glDrawArraysInstanced(mode, startVertex, numVertices, 2);
|
||||||
|
#else
|
||||||
|
setupStereoSide(0);
|
||||||
|
glDrawArrays(mode, startVertex, numVertices);
|
||||||
|
setupStereoSide(1);
|
||||||
|
glDrawArrays(mode, startVertex, numVertices);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_stats._DSNumTriangles += 2 * numVertices / 3;
|
||||||
|
_stats._DSNumDrawcalls += 2;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
glDrawArrays(mode, startVertex, numVertices);
|
||||||
|
_stats._DSNumTriangles += numVertices / 3;
|
||||||
|
_stats._DSNumDrawcalls++;
|
||||||
|
}
|
||||||
|
_stats._DSNumAPIDrawcalls++;
|
||||||
|
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
}
|
||||||
|
|
||||||
void GL45Backend::do_draw(const Batch& batch, size_t paramOffset) {
|
void GL45Backend::do_draw(const Batch& batch, size_t paramOffset) {
|
||||||
Primitive primitiveType = (Primitive)batch._params[paramOffset + 2]._uint;
|
Primitive primitiveType = (Primitive)batch._params[paramOffset + 2]._uint;
|
||||||
GLenum mode = gl::PRIMITIVE_TO_GL[primitiveType];
|
GLenum mode = gl::PRIMITIVE_TO_GL[primitiveType];
|
||||||
|
|
|
@ -229,6 +229,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
void draw(GLenum mode, uint32 numVertices, uint32 startVertex) override;
|
||||||
void recycle() const override;
|
void recycle() const override;
|
||||||
|
|
||||||
GLuint getFramebufferID(const FramebufferPointer& framebuffer) override;
|
GLuint getFramebufferID(const FramebufferPointer& framebuffer) override;
|
||||||
|
|
|
@ -20,6 +20,29 @@ using namespace gpu::gles;
|
||||||
|
|
||||||
const std::string GLESBackend::GLES_VERSION { "GLES" };
|
const std::string GLESBackend::GLES_VERSION { "GLES" };
|
||||||
|
|
||||||
|
void GLESBackend::draw(GLenum mode, uint32 numVertices, uint32 startVertex) {
|
||||||
|
if (isStereo()) {
|
||||||
|
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||||
|
glDrawArraysInstanced(mode, startVertex, numVertices, 2);
|
||||||
|
#else
|
||||||
|
setupStereoSide(0);
|
||||||
|
glDrawArrays(mode, startVertex, numVertices);
|
||||||
|
setupStereoSide(1);
|
||||||
|
glDrawArrays(mode, startVertex, numVertices);
|
||||||
|
#endif
|
||||||
|
_stats._DSNumTriangles += 2 * numVertices / 3;
|
||||||
|
_stats._DSNumDrawcalls += 2;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
glDrawArrays(mode, startVertex, numVertices);
|
||||||
|
_stats._DSNumTriangles += numVertices / 3;
|
||||||
|
_stats._DSNumDrawcalls++;
|
||||||
|
}
|
||||||
|
_stats._DSNumAPIDrawcalls++;
|
||||||
|
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
}
|
||||||
|
|
||||||
void GLESBackend::do_draw(const Batch& batch, size_t paramOffset) {
|
void GLESBackend::do_draw(const Batch& batch, size_t paramOffset) {
|
||||||
Primitive primitiveType = (Primitive)batch._params[paramOffset + 2]._uint;
|
Primitive primitiveType = (Primitive)batch._params[paramOffset + 2]._uint;
|
||||||
GLenum mode = gl::PRIMITIVE_TO_GL[primitiveType];
|
GLenum mode = gl::PRIMITIVE_TO_GL[primitiveType];
|
||||||
|
|
|
@ -126,6 +126,9 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
void draw(GLenum mode, uint32 numVertices, uint32 startVertex) override;
|
||||||
|
|
||||||
GLuint getFramebufferID(const FramebufferPointer& framebuffer) override;
|
GLuint getFramebufferID(const FramebufferPointer& framebuffer) override;
|
||||||
GLFramebuffer* syncGPUObject(const Framebuffer& framebuffer) override;
|
GLFramebuffer* syncGPUObject(const Framebuffer& framebuffer) override;
|
||||||
|
|
||||||
|
|
|
@ -426,6 +426,13 @@ void Batch::generateTextureMips(const TexturePointer& texture) {
|
||||||
_params.emplace_back(_textures.cache(texture));
|
_params.emplace_back(_textures.cache(texture));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Batch::generateTextureMipsWithPipeline(const TexturePointer& texture, int numMips) {
|
||||||
|
ADD_COMMAND(generateTextureMipsWithPipeline);
|
||||||
|
|
||||||
|
_params.emplace_back(_textures.cache(texture));
|
||||||
|
_params.emplace_back(numMips);
|
||||||
|
}
|
||||||
|
|
||||||
void Batch::beginQuery(const QueryPointer& query) {
|
void Batch::beginQuery(const QueryPointer& query) {
|
||||||
ADD_COMMAND(beginQuery);
|
ADD_COMMAND(beginQuery);
|
||||||
|
|
||||||
|
|
|
@ -226,6 +226,8 @@ public:
|
||||||
|
|
||||||
// Generate the mips for a texture
|
// Generate the mips for a texture
|
||||||
void generateTextureMips(const TexturePointer& texture);
|
void generateTextureMips(const TexturePointer& texture);
|
||||||
|
// Generate the mips for a texture using the current pipeline
|
||||||
|
void generateTextureMipsWithPipeline(const TexturePointer& destTexture, int numMips = -1);
|
||||||
|
|
||||||
// Query Section
|
// Query Section
|
||||||
void beginQuery(const QueryPointer& query);
|
void beginQuery(const QueryPointer& query);
|
||||||
|
@ -326,6 +328,7 @@ public:
|
||||||
COMMAND_clearFramebuffer,
|
COMMAND_clearFramebuffer,
|
||||||
COMMAND_blit,
|
COMMAND_blit,
|
||||||
COMMAND_generateTextureMips,
|
COMMAND_generateTextureMips,
|
||||||
|
COMMAND_generateTextureMipsWithPipeline,
|
||||||
|
|
||||||
COMMAND_advance,
|
COMMAND_advance,
|
||||||
|
|
||||||
|
|
20
libraries/gpu/src/gpu/MipGeneration.slh
Normal file
20
libraries/gpu/src/gpu/MipGeneration.slh
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<!
|
||||||
|
// MipGeneration.slh
|
||||||
|
// libraries/gpu/src
|
||||||
|
//
|
||||||
|
// Created by Olivier Prat on 10/16/18.
|
||||||
|
// Copyright 2018 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
|
||||||
|
!>
|
||||||
|
<@if not MIP_GENERATION_SLH@>
|
||||||
|
<@def MIP_GENERATION_SLH@>
|
||||||
|
|
||||||
|
<@include gpu/ShaderConstants.h@>
|
||||||
|
|
||||||
|
layout(binding=GPU_TEXTURE_MIP_CREATION_INPUT) uniform sampler2D texMap;
|
||||||
|
|
||||||
|
in vec2 varTexCoord0;
|
||||||
|
|
||||||
|
<@endif@>
|
|
@ -21,6 +21,9 @@
|
||||||
|
|
||||||
#define GPU_TEXTURE_TRANSFORM_OBJECT 31
|
#define GPU_TEXTURE_TRANSFORM_OBJECT 31
|
||||||
|
|
||||||
|
// Mip creation
|
||||||
|
#define GPU_TEXTURE_MIP_CREATION_INPUT 30
|
||||||
|
|
||||||
#define GPU_STORAGE_TRANSFORM_OBJECT 7
|
#define GPU_STORAGE_TRANSFORM_OBJECT 7
|
||||||
|
|
||||||
#define GPU_ATTR_POSITION 0
|
#define GPU_ATTR_POSITION 0
|
||||||
|
@ -67,7 +70,8 @@ enum Buffer {
|
||||||
namespace texture {
|
namespace texture {
|
||||||
enum Texture {
|
enum Texture {
|
||||||
ObjectTransforms = GPU_TEXTURE_TRANSFORM_OBJECT,
|
ObjectTransforms = GPU_TEXTURE_TRANSFORM_OBJECT,
|
||||||
};
|
MipCreationInput = GPU_TEXTURE_MIP_CREATION_INPUT,
|
||||||
|
};
|
||||||
} // namespace texture
|
} // namespace texture
|
||||||
|
|
||||||
namespace storage {
|
namespace storage {
|
||||||
|
|
|
@ -146,8 +146,10 @@ void DomainHandler::hardReset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DomainHandler::isHardRefusal(int reasonCode) {
|
bool DomainHandler::isHardRefusal(int reasonCode) {
|
||||||
return (reasonCode == (int)ConnectionRefusedReason::ProtocolMismatch || reasonCode == (int)ConnectionRefusedReason::NotAuthorized ||
|
return (reasonCode == (int)ConnectionRefusedReason::ProtocolMismatch ||
|
||||||
reasonCode == (int)ConnectionRefusedReason::TimedOut);
|
reasonCode == (int)ConnectionRefusedReason::TooManyUsers ||
|
||||||
|
reasonCode == (int)ConnectionRefusedReason::NotAuthorized ||
|
||||||
|
reasonCode == (int)ConnectionRefusedReason::TimedOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DomainHandler::getInterstitialModeEnabled() const {
|
bool DomainHandler::getInterstitialModeEnabled() const {
|
||||||
|
@ -496,7 +498,7 @@ bool DomainHandler::reasonSuggestsLogin(ConnectionRefusedReason reasonCode) {
|
||||||
case ConnectionRefusedReason::LoginError:
|
case ConnectionRefusedReason::LoginError:
|
||||||
case ConnectionRefusedReason::NotAuthorized:
|
case ConnectionRefusedReason::NotAuthorized:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
case ConnectionRefusedReason::Unknown:
|
case ConnectionRefusedReason::Unknown:
|
||||||
case ConnectionRefusedReason::ProtocolMismatch:
|
case ConnectionRefusedReason::ProtocolMismatch:
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
this.reticleMinY = MARGIN;
|
this.reticleMinY = MARGIN;
|
||||||
this.reticleMaxY;
|
this.reticleMaxY;
|
||||||
this.parameters = ControllerDispatcherUtils.makeDispatcherModuleParameters(
|
this.parameters = ControllerDispatcherUtils.makeDispatcherModuleParameters(
|
||||||
540,
|
160, // Same as webSurfaceLaserInput.
|
||||||
this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"],
|
this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"],
|
||||||
[],
|
[],
|
||||||
100,
|
100,
|
||||||
|
@ -63,7 +63,6 @@
|
||||||
|
|
||||||
this.processLaser = function(controllerData) {
|
this.processLaser = function(controllerData) {
|
||||||
var controllerLocation = controllerData.controllerLocations[this.hand];
|
var controllerLocation = controllerData.controllerLocations[this.hand];
|
||||||
// var otherModuleRunning = this.getOtherModule().running;
|
|
||||||
if ((controllerData.triggerValues[this.hand] < ControllerDispatcherUtils.TRIGGER_ON_VALUE || !controllerLocation.valid) ||
|
if ((controllerData.triggerValues[this.hand] < ControllerDispatcherUtils.TRIGGER_ON_VALUE || !controllerLocation.valid) ||
|
||||||
this.pointingAtTablet(controllerData)) {
|
this.pointingAtTablet(controllerData)) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -28,7 +28,7 @@ Script.include("/~/system/libraries/utils.js");
|
||||||
this.reticleMaxY = null;
|
this.reticleMaxY = null;
|
||||||
|
|
||||||
this.parameters = makeDispatcherModuleParameters(
|
this.parameters = makeDispatcherModuleParameters(
|
||||||
160,
|
165, // Lower priority than webSurfaceLaserInput and hudOverlayPointer.
|
||||||
this.hand === RIGHT_HAND ? ["rightHand", "rightHandEquip", "rightHandTrigger"] : ["leftHand", "leftHandEquip", "leftHandTrigger"],
|
this.hand === RIGHT_HAND ? ["rightHand", "rightHandEquip", "rightHandTrigger"] : ["leftHand", "leftHandEquip", "leftHandTrigger"],
|
||||||
[],
|
[],
|
||||||
100,
|
100,
|
||||||
|
@ -127,29 +127,41 @@ Script.include("/~/system/libraries/utils.js");
|
||||||
};
|
};
|
||||||
|
|
||||||
this.run = function(controllerData) {
|
this.run = function(controllerData) {
|
||||||
var tabletStylusInput = getEnabledModuleByName(this.hand === RIGHT_HAND ? "RightTabletStylusInput" : "LeftTabletStylusInput");
|
var tabletStylusInput = getEnabledModuleByName(this.hand === RIGHT_HAND
|
||||||
|
? "RightTabletStylusInput" : "LeftTabletStylusInput");
|
||||||
if (tabletStylusInput) {
|
if (tabletStylusInput) {
|
||||||
var tabletReady = tabletStylusInput.isReady(controllerData);
|
var tabletReady = tabletStylusInput.isReady(controllerData);
|
||||||
|
|
||||||
if (tabletReady.active) {
|
if (tabletReady.active) {
|
||||||
return this.exitModule();
|
return this.exitModule();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var overlayLaser = getEnabledModuleByName(this.hand === RIGHT_HAND ? "RightWebSurfaceLaserInput" : "LeftWebSurfaceLaserInput");
|
var webLaser = getEnabledModuleByName(this.hand === RIGHT_HAND
|
||||||
if (overlayLaser) {
|
? "RightWebSurfaceLaserInput" : "LeftWebSurfaceLaserInput");
|
||||||
var overlayLaserReady = overlayLaser.isReady(controllerData);
|
if (webLaser) {
|
||||||
|
var webLaserReady = webLaser.isReady(controllerData);
|
||||||
var target = controllerData.rayPicks[this.hand].objectID;
|
var target = controllerData.rayPicks[this.hand].objectID;
|
||||||
this.sendPointingAtData(controllerData);
|
this.sendPointingAtData(controllerData);
|
||||||
if (overlayLaserReady.active && this.pointingAtTablet(target)) {
|
if (webLaserReady.active && this.pointingAtTablet(target)) {
|
||||||
return this.exitModule();
|
return this.exitModule();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var nearOverlay = getEnabledModuleByName(this.hand === RIGHT_HAND ? "RightNearParentingGrabOverlay" : "LeftNearParentingGrabOverlay");
|
if (!controllerData.triggerClicks[this.hand]) { // Don't grab if trigger pressed when laser starts intersecting.
|
||||||
|
var hudLaser = getEnabledModuleByName(this.hand === RIGHT_HAND
|
||||||
|
? "RightHudOverlayPointer" : "LeftHudOverlayPointer");
|
||||||
|
if (hudLaser) {
|
||||||
|
var hudLaserReady = hudLaser.isReady(controllerData);
|
||||||
|
if (hudLaserReady.active) {
|
||||||
|
return this.exitModule();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var nearOverlay = getEnabledModuleByName(this.hand === RIGHT_HAND
|
||||||
|
? "RightNearParentingGrabOverlay" : "LeftNearParentingGrabOverlay");
|
||||||
if (nearOverlay) {
|
if (nearOverlay) {
|
||||||
var nearOverlayReady = nearOverlay.isReady(controllerData);
|
var nearOverlayReady = nearOverlay.isReady(controllerData);
|
||||||
|
|
||||||
if (nearOverlayReady.active && HMD.tabletID && nearOverlay.grabbedThingID === HMD.tabletID) {
|
if (nearOverlayReady.active && HMD.tabletID && nearOverlay.grabbedThingID === HMD.tabletID) {
|
||||||
return this.exitModule();
|
return this.exitModule();
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,12 +19,13 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||||
function InVREditMode(hand) {
|
function InVREditMode(hand) {
|
||||||
this.hand = hand;
|
this.hand = hand;
|
||||||
this.disableModules = false;
|
this.disableModules = false;
|
||||||
var NO_HAND_LASER = -1; // Invalid hand parameter so that default laser is not displayed.
|
this.running = false;
|
||||||
|
var NO_HAND_LASER = -1; // Invalid hand parameter so that standard laser is not displayed.
|
||||||
this.parameters = makeDispatcherModuleParameters(
|
this.parameters = makeDispatcherModuleParameters(
|
||||||
200, // Not too high otherwise the tablet laser doesn't work.
|
166, // Slightly lower priority than inEditMode.
|
||||||
this.hand === RIGHT_HAND ?
|
this.hand === RIGHT_HAND
|
||||||
["rightHand", "rightHandEquip", "rightHandTrigger"] :
|
? ["rightHand", "rightHandEquip", "rightHandTrigger"]
|
||||||
["leftHand", "leftHandEquip", "leftHandTrigger"],
|
: ["leftHand", "leftHandEquip", "leftHandTrigger"],
|
||||||
[],
|
[],
|
||||||
100,
|
100,
|
||||||
makeLaserParams(NO_HAND_LASER, false)
|
makeLaserParams(NO_HAND_LASER, false)
|
||||||
|
@ -35,6 +36,35 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||||
(HMD.homeButtonID && objectID === HMD.homeButtonID);
|
(HMD.homeButtonID && objectID === HMD.homeButtonID);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// The Shapes app has a non-standard laser: in particular, the laser end dot displays on its own when the laser is
|
||||||
|
// pointing at the Shapes UI. The laser on/off is controlled by this module but the laser is implemented in the Shapes
|
||||||
|
// app.
|
||||||
|
// If, in the future, the Shapes app laser interaction is adopted as a standard UI style then the laser could be
|
||||||
|
// implemented in the controller modules along side the other laser styles.
|
||||||
|
var INVREDIT_MODULE_RUNNING = "Hifi-InVREdit-Module-Running";
|
||||||
|
|
||||||
|
this.runModule = function () {
|
||||||
|
if (!this.running) {
|
||||||
|
Messages.sendLocalMessage(INVREDIT_MODULE_RUNNING, JSON.stringify({
|
||||||
|
hand: this.hand,
|
||||||
|
running: true
|
||||||
|
}));
|
||||||
|
this.running = true;
|
||||||
|
}
|
||||||
|
return makeRunningValues(true, [], []);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.exitModule = function () {
|
||||||
|
if (this.running) {
|
||||||
|
Messages.sendLocalMessage(INVREDIT_MODULE_RUNNING, JSON.stringify({
|
||||||
|
hand: this.hand,
|
||||||
|
running: false
|
||||||
|
}));
|
||||||
|
this.running = false;
|
||||||
|
}
|
||||||
|
return makeRunningValues(false, [], []);
|
||||||
|
};
|
||||||
|
|
||||||
this.isReady = function (controllerData) {
|
this.isReady = function (controllerData) {
|
||||||
if (this.disableModules) {
|
if (this.disableModules) {
|
||||||
return makeRunningValues(true, [], []);
|
return makeRunningValues(true, [], []);
|
||||||
|
@ -45,7 +75,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||||
this.run = function (controllerData) {
|
this.run = function (controllerData) {
|
||||||
// Default behavior if disabling is not enabled.
|
// Default behavior if disabling is not enabled.
|
||||||
if (!this.disableModules) {
|
if (!this.disableModules) {
|
||||||
return makeRunningValues(false, [], []);
|
return this.exitModule();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tablet stylus.
|
// Tablet stylus.
|
||||||
|
@ -55,7 +85,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||||
if (tabletStylusInput) {
|
if (tabletStylusInput) {
|
||||||
var tabletReady = tabletStylusInput.isReady(controllerData);
|
var tabletReady = tabletStylusInput.isReady(controllerData);
|
||||||
if (tabletReady.active) {
|
if (tabletReady.active) {
|
||||||
return makeRunningValues(false, [], []);
|
return this.exitModule();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +97,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||||
var overlayLaserReady = overlayLaser.isReady(controllerData);
|
var overlayLaserReady = overlayLaser.isReady(controllerData);
|
||||||
var target = controllerData.rayPicks[this.hand].objectID;
|
var target = controllerData.rayPicks[this.hand].objectID;
|
||||||
if (overlayLaserReady.active && this.pointingAtTablet(target)) {
|
if (overlayLaserReady.active && this.pointingAtTablet(target)) {
|
||||||
return makeRunningValues(false, [], []);
|
return this.exitModule();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +108,20 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||||
if (nearOverlay) {
|
if (nearOverlay) {
|
||||||
var nearOverlayReady = nearOverlay.isReady(controllerData);
|
var nearOverlayReady = nearOverlay.isReady(controllerData);
|
||||||
if (nearOverlayReady.active && HMD.tabletID && nearOverlay.grabbedThingID === HMD.tabletID) {
|
if (nearOverlayReady.active && HMD.tabletID && nearOverlay.grabbedThingID === HMD.tabletID) {
|
||||||
return makeRunningValues(false, [], []);
|
return this.exitModule();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// HUD overlay.
|
||||||
|
if (!controllerData.triggerClicks[this.hand]) {
|
||||||
|
var hudLaser = getEnabledModuleByName(this.hand === RIGHT_HAND
|
||||||
|
? "RightHudOverlayPointer"
|
||||||
|
: "LeftHudOverlayPointer");
|
||||||
|
if (hudLaser) {
|
||||||
|
var hudLaserReady = hudLaser.isReady(controllerData);
|
||||||
|
if (hudLaserReady.active) {
|
||||||
|
return this.exitModule();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,12 +132,12 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||||
if (teleporter) {
|
if (teleporter) {
|
||||||
var teleporterReady = teleporter.isReady(controllerData);
|
var teleporterReady = teleporter.isReady(controllerData);
|
||||||
if (teleporterReady.active) {
|
if (teleporterReady.active) {
|
||||||
return makeRunningValues(false, [], []);
|
return this.exitModule();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Other behaviors are disabled.
|
// Other behaviors are disabled.
|
||||||
return makeRunningValues(true, [], []);
|
return this.runModule();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1409,7 +1409,6 @@ Script.scriptEnding.connect(function () {
|
||||||
Settings.setValue(SETTING_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE, Menu.isOptionChecked(MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE));
|
Settings.setValue(SETTING_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE, Menu.isOptionChecked(MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE));
|
||||||
Settings.setValue(SETTING_SHOW_ZONES_IN_EDIT_MODE, Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE));
|
Settings.setValue(SETTING_SHOW_ZONES_IN_EDIT_MODE, Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE));
|
||||||
|
|
||||||
Settings.setValue(SETTING_EDIT_PREFIX + MENU_CREATE_ENTITIES_GRABBABLE, Menu.isOptionChecked(MENU_CREATE_ENTITIES_GRABBABLE));
|
|
||||||
Settings.setValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_LARGE, Menu.isOptionChecked(MENU_ALLOW_SELECTION_LARGE));
|
Settings.setValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_LARGE, Menu.isOptionChecked(MENU_ALLOW_SELECTION_LARGE));
|
||||||
Settings.setValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_SMALL, Menu.isOptionChecked(MENU_ALLOW_SELECTION_SMALL));
|
Settings.setValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_SMALL, Menu.isOptionChecked(MENU_ALLOW_SELECTION_SMALL));
|
||||||
Settings.setValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_LIGHTS, Menu.isOptionChecked(MENU_ALLOW_SELECTION_LIGHTS));
|
Settings.setValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_LIGHTS, Menu.isOptionChecked(MENU_ALLOW_SELECTION_LIGHTS));
|
||||||
|
@ -1710,7 +1709,7 @@ function onPromptTextChanged(prompt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handeMenuEvent(menuItem) {
|
function handleMenuEvent(menuItem) {
|
||||||
if (menuItem === "Allow Selecting of Small Models") {
|
if (menuItem === "Allow Selecting of Small Models") {
|
||||||
allowSmallModels = Menu.isOptionChecked("Allow Selecting of Small Models");
|
allowSmallModels = Menu.isOptionChecked("Allow Selecting of Small Models");
|
||||||
} else if (menuItem === "Allow Selecting of Large Models") {
|
} else if (menuItem === "Allow Selecting of Large Models") {
|
||||||
|
@ -1750,6 +1749,8 @@ function handeMenuEvent(menuItem) {
|
||||||
entityIconOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE));
|
entityIconOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE));
|
||||||
} else if (menuItem === MENU_SHOW_ZONES_IN_EDIT_MODE) {
|
} else if (menuItem === MENU_SHOW_ZONES_IN_EDIT_MODE) {
|
||||||
Entities.setDrawZoneBoundaries(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE));
|
Entities.setDrawZoneBoundaries(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE));
|
||||||
|
} else if (menuItem === MENU_CREATE_ENTITIES_GRABBABLE) {
|
||||||
|
Settings.setValue(SETTING_EDIT_PREFIX + menuItem, Menu.isOptionChecked(menuItem));
|
||||||
}
|
}
|
||||||
tooltip.show(false);
|
tooltip.show(false);
|
||||||
}
|
}
|
||||||
|
@ -1875,7 +1876,7 @@ function importSVO(importURL) {
|
||||||
}
|
}
|
||||||
Window.svoImportRequested.connect(importSVO);
|
Window.svoImportRequested.connect(importSVO);
|
||||||
|
|
||||||
Menu.menuItemEvent.connect(handeMenuEvent);
|
Menu.menuItemEvent.connect(handleMenuEvent);
|
||||||
|
|
||||||
var keyPressEvent = function (event) {
|
var keyPressEvent = function (event) {
|
||||||
if (isActive) {
|
if (isActive) {
|
||||||
|
|
|
@ -23,12 +23,17 @@
|
||||||
miniState = null,
|
miniState = null,
|
||||||
|
|
||||||
// Hands.
|
// Hands.
|
||||||
|
NO_HAND = -1,
|
||||||
LEFT_HAND = 0,
|
LEFT_HAND = 0,
|
||||||
RIGHT_HAND = 1,
|
RIGHT_HAND = 1,
|
||||||
HAND_NAMES = ["LeftHand", "RightHand"],
|
HAND_NAMES = ["LeftHand", "RightHand"],
|
||||||
|
|
||||||
// Miscellaneous.
|
// Track controller grabbing state.
|
||||||
HIFI_OBJECT_MANIPULATION_CHANNEL = "Hifi-Object-Manipulation",
|
HIFI_OBJECT_MANIPULATION_CHANNEL = "Hifi-Object-Manipulation",
|
||||||
|
grabbingHand = NO_HAND,
|
||||||
|
grabbedItem = null,
|
||||||
|
|
||||||
|
// Miscellaneous.
|
||||||
tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"),
|
tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"),
|
||||||
DEBUG = false;
|
DEBUG = false;
|
||||||
|
|
||||||
|
@ -737,37 +742,11 @@
|
||||||
setState(MINI_VISIBLE);
|
setState(MINI_VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
function enterMiniShowing(hand) {
|
function checkMiniVisibility() {
|
||||||
miniHand = hand;
|
|
||||||
ui.show(miniHand);
|
|
||||||
miniScaleStart = Date.now();
|
|
||||||
miniScaleTimer = Script.setTimeout(scaleMiniUp, MINI_SCALE_TIMEOUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateMiniShowing() {
|
|
||||||
if (HMD.showTablet) {
|
|
||||||
setState(MINI_HIDDEN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function exitMiniShowing() {
|
|
||||||
if (miniScaleTimer) {
|
|
||||||
Script.clearTimeout(miniScaleTimer);
|
|
||||||
miniScaleTimer = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateMiniVisible() {
|
|
||||||
var showLeft,
|
var showLeft,
|
||||||
showRight;
|
showRight;
|
||||||
|
|
||||||
// Hide mini tablet if tablet proper has been displayed by other means.
|
// Check that the mini tablet should still be visible and if so then ensure it's on the hand that the camera is
|
||||||
if (HMD.showTablet) {
|
|
||||||
setState(MINI_HIDDEN);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that the mini tablet should still be visible and if so then ensure it's on the hand that the camera is
|
|
||||||
// gazing at.
|
// gazing at.
|
||||||
showLeft = shouldShowMini(LEFT_HAND);
|
showLeft = shouldShowMini(LEFT_HAND);
|
||||||
showRight = shouldShowMini(RIGHT_HAND);
|
showRight = shouldShowMini(RIGHT_HAND);
|
||||||
|
@ -790,8 +769,47 @@
|
||||||
setState(MINI_HIDING);
|
setState(MINI_HIDING);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setState(MINI_HIDING);
|
if (grabbedItem === null || grabbingHand !== miniHand) {
|
||||||
|
setState(MINI_HIDING);
|
||||||
|
} else {
|
||||||
|
setState(MINI_HIDDEN);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function enterMiniShowing(hand) {
|
||||||
|
miniHand = hand;
|
||||||
|
ui.show(miniHand);
|
||||||
|
miniScaleStart = Date.now();
|
||||||
|
miniScaleTimer = Script.setTimeout(scaleMiniUp, MINI_SCALE_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateMiniShowing() {
|
||||||
|
// Hide mini tablet if tablet proper has been displayed by other means.
|
||||||
|
if (HMD.showTablet) {
|
||||||
|
setState(MINI_HIDDEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide mini tablet if it should no longer be visible.
|
||||||
|
checkMiniVisibility();
|
||||||
|
}
|
||||||
|
|
||||||
|
function exitMiniShowing() {
|
||||||
|
if (miniScaleTimer) {
|
||||||
|
Script.clearTimeout(miniScaleTimer);
|
||||||
|
miniScaleTimer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateMiniVisible() {
|
||||||
|
// Hide mini tablet if tablet proper has been displayed by other means.
|
||||||
|
if (HMD.showTablet) {
|
||||||
|
setState(MINI_HIDDEN);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide mini tablet if it should no longer be visible.
|
||||||
|
checkMiniVisibility();
|
||||||
|
|
||||||
// If state hasn't changed, update mini tablet rotation.
|
// If state hasn't changed, update mini tablet rotation.
|
||||||
if (miniState === MINI_VISIBLE) {
|
if (miniState === MINI_VISIBLE) {
|
||||||
|
@ -973,6 +991,21 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Track grabbed state and item.
|
||||||
|
switch (message.action) {
|
||||||
|
case "grab":
|
||||||
|
grabbingHand = HAND_NAMES.indexOf(message.joint);
|
||||||
|
grabbedItem = message.grabbedEntity;
|
||||||
|
break;
|
||||||
|
case "release":
|
||||||
|
grabbingHand = NO_HAND;
|
||||||
|
grabbedItem = null;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error("Unexpected grab message!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (message.grabbedEntity !== HMD.tabletID && message.grabbedEntity !== ui.getMiniTabletID()) {
|
if (message.grabbedEntity !== HMD.tabletID && message.grabbedEntity !== ui.getMiniTabletID()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,14 +5,20 @@
|
||||||
"Oops! Protocol version mismatch.",
|
"Oops! Protocol version mismatch.",
|
||||||
"Oops! Not authorized to join domain.",
|
"Oops! Not authorized to join domain.",
|
||||||
"Oops! Connection timed out.",
|
"Oops! Connection timed out.",
|
||||||
|
"Oops! The domain is full.",
|
||||||
"Oops! Something went wrong."
|
"Oops! Something went wrong."
|
||||||
];
|
];
|
||||||
|
|
||||||
var PROTOCOL_VERSION_MISMATCH = 1;
|
var PROTOCOL_VERSION_MISMATCH = 1;
|
||||||
var NOT_AUTHORIZED = 3;
|
var NOT_AUTHORIZED = 3;
|
||||||
|
var DOMAIN_FULL = 4;
|
||||||
var TIMEOUT = 5;
|
var TIMEOUT = 5;
|
||||||
var hardRefusalErrors = [PROTOCOL_VERSION_MISMATCH,
|
var hardRefusalErrors = [
|
||||||
NOT_AUTHORIZED, TIMEOUT];
|
PROTOCOL_VERSION_MISMATCH,
|
||||||
|
NOT_AUTHORIZED,
|
||||||
|
TIMEOUT,
|
||||||
|
DOMAIN_FULL
|
||||||
|
];
|
||||||
var timer = null;
|
var timer = null;
|
||||||
var isErrorState = false;
|
var isErrorState = false;
|
||||||
|
|
||||||
|
@ -26,7 +32,7 @@
|
||||||
return ERROR_MESSAGE_MAP[errorMessageMapIndex];
|
return ERROR_MESSAGE_MAP[errorMessageMapIndex];
|
||||||
} else {
|
} else {
|
||||||
// some other text.
|
// some other text.
|
||||||
return ERROR_MESSAGE_MAP[4];
|
return ERROR_MESSAGE_MAP[ERROR_MESSAGE_MAP.length - 1];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,10 @@ try {
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeFromStoryIDsToMaybeDelete(story_id) {
|
function removeFromStoryIDsToMaybeDelete(story_id) {
|
||||||
storyIDsToMaybeDelete.splice(storyIDsToMaybeDelete.indexOf(story_id), 1);
|
story_id = parseInt(story_id);
|
||||||
|
if (storyIDsToMaybeDelete.indexOf(story_id) > -1) {
|
||||||
|
storyIDsToMaybeDelete.splice(storyIDsToMaybeDelete.indexOf(story_id), 1);
|
||||||
|
}
|
||||||
print('storyIDsToMaybeDelete[] now:', JSON.stringify(storyIDsToMaybeDelete));
|
print('storyIDsToMaybeDelete[] now:', JSON.stringify(storyIDsToMaybeDelete));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,6 +261,7 @@ function onMessage(message) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'removeFromStoryIDsToMaybeDelete':
|
case 'removeFromStoryIDsToMaybeDelete':
|
||||||
|
console.log("Facebook OR Twitter button clicked for story_id " + message.story_id);
|
||||||
removeFromStoryIDsToMaybeDelete(message.story_id);
|
removeFromStoryIDsToMaybeDelete(message.story_id);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -333,11 +337,13 @@ function fillImageDataFromPrevious() {
|
||||||
var previousAnimatedSnapStoryID = Settings.getValue("previousAnimatedSnapStoryID");
|
var previousAnimatedSnapStoryID = Settings.getValue("previousAnimatedSnapStoryID");
|
||||||
var previousAnimatedSnapBlastingDisabled = Settings.getValue("previousAnimatedSnapBlastingDisabled");
|
var previousAnimatedSnapBlastingDisabled = Settings.getValue("previousAnimatedSnapBlastingDisabled");
|
||||||
var previousAnimatedSnapHifiSharingDisabled = Settings.getValue("previousAnimatedSnapHifiSharingDisabled");
|
var previousAnimatedSnapHifiSharingDisabled = Settings.getValue("previousAnimatedSnapHifiSharingDisabled");
|
||||||
|
|
||||||
snapshotOptions = {
|
snapshotOptions = {
|
||||||
containsGif: previousAnimatedSnapPath !== "",
|
containsGif: previousAnimatedSnapPath !== "",
|
||||||
processingGif: false,
|
processingGif: false,
|
||||||
shouldUpload: false,
|
shouldUpload: false,
|
||||||
canBlast: snapshotDomainID === Settings.getValue("previousSnapshotDomainID"),
|
canBlast: snapshotDomainID === Settings.getValue("previousSnapshotDomainID") &&
|
||||||
|
snapshotDomainID === location.domainID,
|
||||||
isLoggedIn: isLoggedIn
|
isLoggedIn: isLoggedIn
|
||||||
};
|
};
|
||||||
imageData = [];
|
imageData = [];
|
||||||
|
@ -369,7 +375,8 @@ function snapshotUploaded(isError, reply) {
|
||||||
isGif = fileExtensionMatches(imageURL, "gif"),
|
isGif = fileExtensionMatches(imageURL, "gif"),
|
||||||
ignoreGifSnapshotData = false,
|
ignoreGifSnapshotData = false,
|
||||||
ignoreStillSnapshotData = false;
|
ignoreStillSnapshotData = false;
|
||||||
storyIDsToMaybeDelete.push(storyID);
|
storyIDsToMaybeDelete.push(parseInt(storyID));
|
||||||
|
print('storyIDsToMaybeDelete[] now:', JSON.stringify(storyIDsToMaybeDelete));
|
||||||
if (isGif) {
|
if (isGif) {
|
||||||
if (mostRecentGifSnapshotFilename !== replyJson.user_story.details.original_image_file_name) {
|
if (mostRecentGifSnapshotFilename !== replyJson.user_story.details.original_image_file_name) {
|
||||||
ignoreGifSnapshotData = true;
|
ignoreGifSnapshotData = true;
|
||||||
|
|
|
@ -338,13 +338,15 @@ const HifiNotificationType = hfNotifications.NotificationType;
|
||||||
var pendingNotifications = {}
|
var pendingNotifications = {}
|
||||||
var notificationState = NotificationState.UNNOTIFIED;
|
var notificationState = NotificationState.UNNOTIFIED;
|
||||||
|
|
||||||
function setNotificationState (notificationType, pending = true) {
|
function setNotificationState (notificationType, pending = undefined) {
|
||||||
pendingNotifications[notificationType] = pending;
|
if (pending !== undefined) {
|
||||||
notificationState = NotificationState.UNNOTIFIED;
|
pendingNotifications[notificationType] = pending;
|
||||||
for (var key in pendingNotifications) {
|
notificationState = NotificationState.UNNOTIFIED;
|
||||||
if (pendingNotifications[key]) {
|
for (var key in pendingNotifications) {
|
||||||
notificationState = NotificationState.NOTIFIED;
|
if (pendingNotifications[key]) {
|
||||||
break;
|
notificationState = NotificationState.NOTIFIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateTrayMenu(homeServer ? homeServer.state : ProcessGroupStates.STOPPED);
|
updateTrayMenu(homeServer ? homeServer.state : ProcessGroupStates.STOPPED);
|
||||||
|
@ -568,7 +570,42 @@ function updateLabels(serverState) {
|
||||||
labels.people.icon = pendingNotifications[HifiNotificationType.PEOPLE] ? menuNotificationIcon : null;
|
labels.people.icon = pendingNotifications[HifiNotificationType.PEOPLE] ? menuNotificationIcon : null;
|
||||||
labels.wallet.icon = pendingNotifications[HifiNotificationType.WALLET] ? menuNotificationIcon : null;
|
labels.wallet.icon = pendingNotifications[HifiNotificationType.WALLET] ? menuNotificationIcon : null;
|
||||||
labels.marketplace.icon = pendingNotifications[HifiNotificationType.MARKETPLACE] ? menuNotificationIcon : null;
|
labels.marketplace.icon = pendingNotifications[HifiNotificationType.MARKETPLACE] ? menuNotificationIcon : null;
|
||||||
|
var onlineUsers = trayNotifications.getOnlineUsers();
|
||||||
|
delete labels.people.submenu;
|
||||||
|
if (onlineUsers) {
|
||||||
|
for (var name in onlineUsers) {
|
||||||
|
if(labels.people.submenu == undefined) {
|
||||||
|
labels.people.submenu = [];
|
||||||
|
}
|
||||||
|
labels.people.submenu.push({
|
||||||
|
label: name,
|
||||||
|
enabled: (onlineUsers[name].location != undefined),
|
||||||
|
click: function (item) {
|
||||||
|
setNotificationState(HifiNotificationType.PEOPLE, false);
|
||||||
|
if(onlineUsers[item.label] && onlineUsers[item.label].location) {
|
||||||
|
StartInterface("hifi://" + onlineUsers[item.label].location.root.name + onlineUsers[item.label].location.path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var currentStories = trayNotifications.getCurrentStories();
|
||||||
|
delete labels.goto.submenu;
|
||||||
|
if (currentStories) {
|
||||||
|
for (var location in currentStories) {
|
||||||
|
if(labels.goto.submenu == undefined) {
|
||||||
|
labels.goto.submenu = [];
|
||||||
|
}
|
||||||
|
labels.goto.submenu.push({
|
||||||
|
label: "event in " + location,
|
||||||
|
location: location,
|
||||||
|
click: function (item) {
|
||||||
|
setNotificationState(HifiNotificationType.GOTO, false);
|
||||||
|
StartInterface("hifi://" + item.location + currentStories[item.location].path);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateTrayMenu(serverState) {
|
function updateTrayMenu(serverState) {
|
||||||
|
@ -919,6 +956,8 @@ app.on('ready', function() {
|
||||||
trayNotifications.startPolling();
|
trayNotifications.startPolling();
|
||||||
}
|
}
|
||||||
updateTrayMenu(ProcessGroupStates.STOPPED);
|
updateTrayMenu(ProcessGroupStates.STOPPED);
|
||||||
|
|
||||||
maybeInstallDefaultContentSet(onContentLoaded);
|
if (isServerInstalled()) {
|
||||||
|
maybeInstallDefaultContentSet(onContentLoaded);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -73,11 +73,17 @@ HifiNotification.prototype = {
|
||||||
text = this.data + " of your connections are online."
|
text = this.data + " of your connections are online."
|
||||||
}
|
}
|
||||||
message = "Click to open PEOPLE.";
|
message = "Click to open PEOPLE.";
|
||||||
url="hifiapp:PEOPLE"
|
url="hifiapp:PEOPLE";
|
||||||
} else {
|
} else {
|
||||||
text = this.data.username + " is available in " + this.data.location.root.name + ".";
|
if (this.data.location) {
|
||||||
message = "Click to join them.";
|
text = this.data.username + " is available in " + this.data.location.root.name + ".";
|
||||||
url="hifi://" + this.data.location.root.name + this.data.location.path;
|
message = "Click to join them.";
|
||||||
|
url="hifi://" + this.data.location.root.name + this.data.location.path;
|
||||||
|
} else {
|
||||||
|
text = this.data.username + " is online.";
|
||||||
|
message = "Click to open PEOPLE.";
|
||||||
|
url="hifiapp:PEOPLE";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -136,7 +142,8 @@ HifiNotification.prototype = {
|
||||||
function HifiNotifications(config, menuNotificationCallback) {
|
function HifiNotifications(config, menuNotificationCallback) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.menuNotificationCallback = menuNotificationCallback;
|
this.menuNotificationCallback = menuNotificationCallback;
|
||||||
this.onlineUsers = new Set([]);
|
this.onlineUsers = {};
|
||||||
|
this.currentStories = {};
|
||||||
this.storiesSince = new Date(this.config.get("storiesNotifySince", "1970-01-01T00:00:00.000Z"));
|
this.storiesSince = new Date(this.config.get("storiesNotifySince", "1970-01-01T00:00:00.000Z"));
|
||||||
this.peopleSince = new Date(this.config.get("peopleNotifySince", "1970-01-01T00:00:00.000Z"));
|
this.peopleSince = new Date(this.config.get("peopleNotifySince", "1970-01-01T00:00:00.000Z"));
|
||||||
this.walletSince = new Date(this.config.get("walletNotifySince", "1970-01-01T00:00:00.000Z"));
|
this.walletSince = new Date(this.config.get("walletNotifySince", "1970-01-01T00:00:00.000Z"));
|
||||||
|
@ -213,6 +220,12 @@ HifiNotifications.prototype = {
|
||||||
clearInterval(this.marketplacePollTimer);
|
clearInterval(this.marketplacePollTimer);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
getOnlineUsers: function () {
|
||||||
|
return this.onlineUsers;
|
||||||
|
},
|
||||||
|
getCurrentStories: function () {
|
||||||
|
return this.currentStories;
|
||||||
|
},
|
||||||
_showNotification: function () {
|
_showNotification: function () {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
|
|
||||||
|
@ -225,7 +238,7 @@ HifiNotifications.prototype = {
|
||||||
// previous notification immediately when a
|
// previous notification immediately when a
|
||||||
// new one is submitted
|
// new one is submitted
|
||||||
_this.pendingNotifications.shift();
|
_this.pendingNotifications.shift();
|
||||||
if(_this.pendingNotifications.length > 0) {
|
if (_this.pendingNotifications.length > 0) {
|
||||||
_this._showNotification();
|
_this._showNotification();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -289,7 +302,6 @@ HifiNotifications.prototype = {
|
||||||
finished(false);
|
finished(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log(content);
|
|
||||||
if (!content.total_entries) {
|
if (!content.total_entries) {
|
||||||
finished(true, token);
|
finished(true, token);
|
||||||
return;
|
return;
|
||||||
|
@ -313,7 +325,6 @@ HifiNotifications.prototype = {
|
||||||
notifyData = content.data.updates;
|
notifyData = content.data.updates;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyData.forEach(function (notifyDataEntry) {
|
notifyData.forEach(function (notifyDataEntry) {
|
||||||
_this._addNotification(new HifiNotification(notifyType, notifyDataEntry));
|
_this._addNotification(new HifiNotification(notifyType, notifyDataEntry));
|
||||||
});
|
});
|
||||||
|
@ -346,7 +357,7 @@ HifiNotifications.prototype = {
|
||||||
'include_actions=announcement',
|
'include_actions=announcement',
|
||||||
'restriction=open,hifi',
|
'restriction=open,hifi',
|
||||||
'require_online=true',
|
'require_online=true',
|
||||||
'per_page=1'
|
'per_page=' + MAX_NOTIFICATION_ITEMS
|
||||||
];
|
];
|
||||||
var url = METAVERSE_SERVER_URL + STORIES_URL + '?' + options.join('&');
|
var url = METAVERSE_SERVER_URL + STORIES_URL + '?' + options.join('&');
|
||||||
// call a second time to determine if there are no more stories and we should
|
// call a second time to determine if there are no more stories and we should
|
||||||
|
@ -357,7 +368,34 @@ HifiNotifications.prototype = {
|
||||||
'bearer': token
|
'bearer': token
|
||||||
}
|
}
|
||||||
}, function (error, data) {
|
}, function (error, data) {
|
||||||
_this._pollToDisableHighlight(NotificationType.GOTO, error, data);
|
if (error || !data.body) {
|
||||||
|
console.log("Error: unable to get " + url);
|
||||||
|
finished(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var content = JSON.parse(data.body);
|
||||||
|
if (!content || content.status != 'success') {
|
||||||
|
console.log("Error: unable to get " + url);
|
||||||
|
finished(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!content.total_entries) {
|
||||||
|
finished(true, token);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!content.total_entries) {
|
||||||
|
_this.menuNotificationCallback(NotificationType.GOTO, false);
|
||||||
|
}
|
||||||
|
_this.currentStories = {};
|
||||||
|
content.user_stories.forEach(function (story) {
|
||||||
|
// only show a single instance of each story location
|
||||||
|
// in the menu. This may cause issues with domains
|
||||||
|
// where the story locations are significantly different
|
||||||
|
// for each story.
|
||||||
|
_this.currentStories[story.place_name] = story;
|
||||||
|
});
|
||||||
|
_this.menuNotificationCallback(NotificationType.GOTO);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -400,20 +438,19 @@ HifiNotifications.prototype = {
|
||||||
console.log("Error: unable to get " + url);
|
console.log("Error: unable to get " + url);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
console.log(content);
|
|
||||||
if (!content.total_entries) {
|
if (!content.total_entries) {
|
||||||
_this.menuNotificationCallback(NotificationType.PEOPLE, false);
|
_this.menuNotificationCallback(NotificationType.PEOPLE, false);
|
||||||
_this.onlineUsers = new Set([]);
|
_this.onlineUsers = {};
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentUsers = new Set([]);
|
var currentUsers = {};
|
||||||
var newUsers = new Set([]);
|
var newUsers = new Set([]);
|
||||||
content.data.users.forEach(function (user) {
|
content.data.users.forEach(function (user) {
|
||||||
currentUsers.add(user.username);
|
currentUsers[user.username] = user;
|
||||||
if (!_this.onlineUsers.has(user.username)) {
|
if (!(user.username in _this.onlineUsers)) {
|
||||||
newUsers.add(user);
|
newUsers.add(user);
|
||||||
_this.onlineUsers.add(user.username);
|
_this.onlineUsers[user.username] = user;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
_this.onlineUsers = currentUsers;
|
_this.onlineUsers = currentUsers;
|
||||||
|
|
Loading…
Reference in a new issue