mirror of
https://github.com/overte-org/overte.git
synced 2025-04-25 20:16:16 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into pop_dynamicTestsMaster
This commit is contained in:
commit
91333cdf7b
79 changed files with 782 additions and 890 deletions
|
@ -30,6 +30,8 @@
|
|||
#include <UUID.h>
|
||||
#include <WebSocketServerClass.h>
|
||||
|
||||
#include <EntityScriptClient.h> // for EntityScriptServerServices
|
||||
|
||||
#include "EntityScriptServerLogging.h"
|
||||
#include "../entities/AssignmentParentFinder.h"
|
||||
|
||||
|
@ -68,6 +70,9 @@ EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : ThreadedAssig
|
|||
DependencyManager::set<ScriptCache>();
|
||||
DependencyManager::set<ScriptEngines>(ScriptEngine::ENTITY_SERVER_SCRIPT);
|
||||
|
||||
DependencyManager::set<EntityScriptServerServices>();
|
||||
|
||||
|
||||
// Needed to ensure the creation of the DebugDraw instance on the main thread
|
||||
DebugDraw::getInstance();
|
||||
|
||||
|
@ -583,6 +588,7 @@ void EntityScriptServer::aboutToFinish() {
|
|||
// cleanup the AudioInjectorManager (and any still running injectors)
|
||||
DependencyManager::destroy<AudioInjectorManager>();
|
||||
DependencyManager::destroy<ScriptEngines>();
|
||||
DependencyManager::destroy<EntityScriptServerServices>();
|
||||
|
||||
// cleanup codec & encoder
|
||||
if (_codec && _encoder) {
|
||||
|
|
|
@ -14,6 +14,12 @@
|
|||
var isWindowFocused = true;
|
||||
var isKeyboardRaised = false;
|
||||
var isNumericKeyboard = false;
|
||||
var isPasswordField = false;
|
||||
|
||||
function shouldSetPasswordField() {
|
||||
var nodeType = document.activeElement.type;
|
||||
return nodeType === "password";
|
||||
}
|
||||
|
||||
function shouldRaiseKeyboard() {
|
||||
var nodeName = document.activeElement.nodeName;
|
||||
|
@ -53,12 +59,14 @@
|
|||
setInterval(function () {
|
||||
var keyboardRaised = shouldRaiseKeyboard();
|
||||
var numericKeyboard = shouldSetNumeric();
|
||||
var passwordField = shouldSetPasswordField();
|
||||
|
||||
if (isWindowFocused && (keyboardRaised !== isKeyboardRaised || numericKeyboard !== isNumericKeyboard)) {
|
||||
if (isWindowFocused &&
|
||||
(keyboardRaised !== isKeyboardRaised || numericKeyboard !== isNumericKeyboard || passwordField !== isPasswordField)) {
|
||||
|
||||
if (typeof EventBridge !== "undefined" && EventBridge !== null) {
|
||||
EventBridge.emitWebEvent(
|
||||
keyboardRaised ? ("_RAISE_KEYBOARD" + (numericKeyboard ? "_NUMERIC" : "")) : "_LOWER_KEYBOARD"
|
||||
keyboardRaised ? ("_RAISE_KEYBOARD" + (numericKeyboard ? "_NUMERIC" : "") + (passwordField ? "_PASSWORD" : "")) : "_LOWER_KEYBOARD"
|
||||
);
|
||||
} else {
|
||||
if (numWarnings < MAX_WARNINGS) {
|
||||
|
@ -74,6 +82,7 @@
|
|||
|
||||
isKeyboardRaised = keyboardRaised;
|
||||
isNumericKeyboard = numericKeyboard;
|
||||
isPasswordField = passwordField;
|
||||
}
|
||||
}, POLL_FREQUENCY);
|
||||
|
||||
|
|
|
@ -119,6 +119,7 @@ Item {
|
|||
width: parent.width
|
||||
focus: true
|
||||
label: "Username or Email"
|
||||
activeFocusOnPress: true
|
||||
|
||||
ShortcutText {
|
||||
anchors {
|
||||
|
@ -135,6 +136,9 @@ Item {
|
|||
|
||||
onLinkActivated: loginDialog.openUrl(link)
|
||||
}
|
||||
onFocusChanged: {
|
||||
root.text = "";
|
||||
}
|
||||
}
|
||||
|
||||
TextField {
|
||||
|
@ -143,6 +147,7 @@ Item {
|
|||
|
||||
label: "Password"
|
||||
echoMode: showPassword.checked ? TextInput.Normal : TextInput.Password
|
||||
activeFocusOnPress: true
|
||||
|
||||
ShortcutText {
|
||||
anchors {
|
||||
|
@ -159,6 +164,10 @@ Item {
|
|||
|
||||
onLinkActivated: loginDialog.openUrl(link)
|
||||
}
|
||||
onFocusChanged: {
|
||||
root.text = "";
|
||||
root.isPassword = true;
|
||||
}
|
||||
}
|
||||
|
||||
CheckBoxQQC2 {
|
||||
|
@ -233,18 +242,6 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
// Override ScrollingWindow's keyboard that would be at very bottom of dialog.
|
||||
Keyboard {
|
||||
raised: keyboardEnabled && keyboardRaised
|
||||
numeric: punctuationMode
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
bottomMargin: keyboardRaised ? 2 * hifi.dimensions.contentSpacing.y : 0
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
root.title = qsTr("Sign Into High Fidelity")
|
||||
root.iconText = "<"
|
||||
|
|
|
@ -108,12 +108,17 @@ Item {
|
|||
id: emailField
|
||||
width: parent.width
|
||||
label: "Email"
|
||||
activeFocusOnPress: true
|
||||
onFocusChanged: {
|
||||
root.text = "";
|
||||
}
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: usernameField
|
||||
width: parent.width
|
||||
label: "Username"
|
||||
activeFocusOnPress: true
|
||||
|
||||
ShortcutText {
|
||||
anchors {
|
||||
|
@ -128,6 +133,9 @@ Item {
|
|||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
color: hifi.colors.blueAccent
|
||||
onFocusChanged: {
|
||||
root.text = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -136,6 +144,7 @@ Item {
|
|||
width: parent.width
|
||||
label: "Password"
|
||||
echoMode: TextInput.Password
|
||||
activeFocusOnPress: true
|
||||
|
||||
ShortcutText {
|
||||
anchors {
|
||||
|
@ -151,6 +160,11 @@ Item {
|
|||
|
||||
color: hifi.colors.blueAccent
|
||||
}
|
||||
|
||||
onFocusChanged: {
|
||||
root.text = "";
|
||||
root.isPassword = focus
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
|
@ -202,18 +216,6 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
// Override ScrollingWindow's keyboard that would be at very bottom of dialog.
|
||||
Keyboard {
|
||||
raised: keyboardEnabled && keyboardRaised
|
||||
numeric: punctuationMode
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
bottomMargin: keyboardRaised ? 2 * hifi.dimensions.contentSpacing.y : 0
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
root.title = qsTr("Create an Account")
|
||||
root.iconText = "<"
|
||||
|
|
|
@ -39,6 +39,10 @@ Rectangle {
|
|||
property bool shiftMode: false
|
||||
property bool numericShiftMode: false
|
||||
|
||||
onRaisedChanged: {
|
||||
mirroredText = "";
|
||||
}
|
||||
|
||||
function resetShiftMode(mode) {
|
||||
shiftMode = mode;
|
||||
shiftKey.resetToggledMode(mode);
|
||||
|
|
|
@ -16,6 +16,7 @@ Item {
|
|||
property bool keyboardEnabled: false
|
||||
property bool keyboardRaised: false
|
||||
property bool punctuationMode: false
|
||||
property bool passwordField: false
|
||||
property bool isDesktop: false
|
||||
property alias webView: web.webViewCore
|
||||
property alias profile: web.webViewCoreProfile
|
||||
|
@ -165,6 +166,11 @@ Item {
|
|||
id: keyboard
|
||||
raised: parent.keyboardEnabled && parent.keyboardRaised
|
||||
numeric: parent.punctuationMode
|
||||
password: parent.passwordField
|
||||
|
||||
onPasswordChanged: {
|
||||
keyboard.mirroredText = "";
|
||||
}
|
||||
|
||||
anchors {
|
||||
left: parent.left
|
||||
|
|
|
@ -13,6 +13,7 @@ Item {
|
|||
property bool keyboardEnabled: true // FIXME - Keyboard HMD only: Default to false
|
||||
property bool keyboardRaised: false
|
||||
property bool punctuationMode: false
|
||||
property bool passwordField: false
|
||||
property alias flickable: webroot.interactive
|
||||
|
||||
// FIXME - Keyboard HMD only: Make Interface either set keyboardRaised property directly in OffscreenQmlSurface
|
||||
|
@ -50,6 +51,7 @@ Item {
|
|||
id: keyboard
|
||||
raised: parent.keyboardEnabled && parent.keyboardRaised
|
||||
numeric: parent.punctuationMode
|
||||
password: parent.passwordField
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
|
|
|
@ -37,6 +37,8 @@ TabletModalWindow {
|
|||
property bool keyboardEnabled: false
|
||||
property bool keyboardRaised: false
|
||||
property bool punctuationMode: false
|
||||
property bool isPassword: false
|
||||
property alias text: loginKeyboard.mirroredText
|
||||
|
||||
readonly property bool isTablet: true
|
||||
|
||||
|
@ -130,6 +132,7 @@ TabletModalWindow {
|
|||
id: loginKeyboard
|
||||
raised: root.keyboardEnabled && root.keyboardRaised
|
||||
numeric: root.punctuationMode
|
||||
password: root.isPassword
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
import QtQuick 2.5
|
||||
import "../styles-uit"
|
||||
import "../controls-uit" as HifiControls
|
||||
import QtQuick.Controls 2.2
|
||||
|
||||
Item {
|
||||
id: root;
|
||||
|
@ -20,7 +21,7 @@ Item {
|
|||
property var defaultThumbnails: [];
|
||||
property var defaultFulls: [];
|
||||
|
||||
SkyboxSelectionModel {
|
||||
ListModel {
|
||||
id: skyboxModel;
|
||||
}
|
||||
|
||||
|
@ -38,47 +39,22 @@ Item {
|
|||
|
||||
function sortSkyboxes(response) {
|
||||
var arr = JSON.parse(response);
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
var arrLength = arr.length;
|
||||
for (var i = 0; i < arrLength; i++) {
|
||||
defaultThumbnails.push(arr[i].thumb);
|
||||
defaultFulls.push(arr[i].full);
|
||||
skyboxModel.append({});
|
||||
}
|
||||
setDefaultSkyboxes();
|
||||
setSkyboxes();
|
||||
}
|
||||
|
||||
function setDefaultSkyboxes() {
|
||||
function setSkyboxes() {
|
||||
for (var i = 0; i < skyboxModel.count; i++) {
|
||||
skyboxModel.setProperty(i, "thumbnailPath", defaultThumbnails[i]);
|
||||
skyboxModel.setProperty(i, "fullSkyboxPath", defaultFulls[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function shuffle(array) {
|
||||
var tmp, current, top = array.length;
|
||||
if (top) {
|
||||
while (--top) {
|
||||
current = Math.floor(Math.random() * (top + 1));
|
||||
tmp = array[current];
|
||||
array[current] = array[top];
|
||||
array[top] = tmp;
|
||||
}
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
function chooseRandom() {
|
||||
for (var a = [], i=0; i < defaultFulls.length; ++i) {
|
||||
a[i] = i;
|
||||
}
|
||||
|
||||
a = shuffle(a);
|
||||
|
||||
for (var i = 0; i < skyboxModel.count; i++) {
|
||||
skyboxModel.setProperty(i, "thumbnailPath", defaultThumbnails[a[i]]);
|
||||
skyboxModel.setProperty(i, "fullSkyboxPath", defaultFulls[a[i]]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Component.onCompleted: {
|
||||
getSkyboxes();
|
||||
}
|
||||
|
@ -116,33 +92,18 @@ Item {
|
|||
horizontalAlignment: Text.AlignHCenter;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
}
|
||||
HifiControls.Button {
|
||||
id: randomButton
|
||||
text: "Randomize"
|
||||
color: hifi.buttons.blue
|
||||
colorScheme: root.colorScheme
|
||||
width: 100
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 5
|
||||
anchors.rightMargin: 40
|
||||
onClicked: {
|
||||
chooseRandom()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GridView {
|
||||
id: gridView
|
||||
interactive: false
|
||||
interactive: true
|
||||
clip: true
|
||||
anchors.top: titleBarContainer.bottom
|
||||
anchors.topMargin: 20
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: 400
|
||||
height: parent.height
|
||||
anchors.bottom: parent.bottom
|
||||
currentIndex: -1
|
||||
|
||||
cellWidth: 200
|
||||
cellHeight: 200
|
||||
model: skyboxModel
|
||||
|
@ -168,6 +129,14 @@ Item {
|
|||
}
|
||||
}
|
||||
}
|
||||
ScrollBar.vertical: ScrollBar {
|
||||
parent: gridView.parent
|
||||
anchors.top: gridView.top
|
||||
anchors.left: gridView.right
|
||||
anchors.bottom: gridView.bottom
|
||||
anchors.leftMargin: 10
|
||||
width: 19
|
||||
}
|
||||
}
|
||||
|
||||
signal sendToScript(var message);
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
//
|
||||
// SkyboxSelectionModel.qml
|
||||
// qml/hifi
|
||||
//
|
||||
// Created by Cain Kilgore on 21st October 2017
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
|
||||
ListModel {
|
||||
id: root;
|
||||
ListElement{
|
||||
thumbnailPath: "http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/thumbnails/thumb_1.jpg"
|
||||
fullSkyboxPath: "http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/skyboxes/1.jpg"
|
||||
}
|
||||
ListElement{
|
||||
thumbnailPath: "http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/thumbnails/thumb_1.jpg"
|
||||
fullSkyboxPath: "http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/skyboxes/1.jpg"
|
||||
}
|
||||
ListElement{
|
||||
thumbnailPath: "http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/thumbnails/thumb_1.jpg"
|
||||
fullSkyboxPath: "http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/skyboxes/1.jpg"
|
||||
}
|
||||
ListElement{
|
||||
thumbnailPath: "http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/thumbnails/thumb_1.jpg"
|
||||
fullSkyboxPath: "http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/skyboxes/1.jpg"
|
||||
}
|
||||
ListElement{
|
||||
thumbnailPath: "http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/thumbnails/thumb_1.jpg"
|
||||
fullSkyboxPath: "http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/skyboxes/1.jpg"
|
||||
}
|
||||
ListElement{
|
||||
thumbnailPath: "http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/thumbnails/thumb_1.jpg"
|
||||
fullSkyboxPath: "http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/skyboxes/1.jpg"
|
||||
}
|
||||
}
|
|
@ -39,7 +39,8 @@ Rectangle {
|
|||
property bool itemIsJson: true;
|
||||
property bool shouldBuyWithControlledFailure: false;
|
||||
property bool debugCheckoutSuccess: false;
|
||||
property bool canRezCertifiedItems: Entities.canRezCertified || Entities.canRezTmpCertified;
|
||||
property bool canRezCertifiedItems: Entities.canRezCertified() || Entities.canRezTmpCertified();
|
||||
property bool isWearable;
|
||||
// Style
|
||||
color: hifi.colors.white;
|
||||
Hifi.QmlCommerce {
|
||||
|
@ -80,6 +81,7 @@ Rectangle {
|
|||
root.activeView = "checkoutFailure";
|
||||
} else {
|
||||
root.itemHref = result.data.download_url;
|
||||
root.isWearable = result.data.categories.indexOf("Wearables") > -1;
|
||||
root.activeView = "checkoutSuccess";
|
||||
}
|
||||
}
|
||||
|
@ -592,7 +594,7 @@ Rectangle {
|
|||
height: 50;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
text: "Rez It"
|
||||
text: root.isWearable ? "Wear It" : "Rez It"
|
||||
onClicked: {
|
||||
if (urlHandler.canHandleUrl(root.itemHref)) {
|
||||
urlHandler.handleUrl(root.itemHref);
|
||||
|
@ -603,7 +605,7 @@ Rectangle {
|
|||
}
|
||||
RalewaySemiBold {
|
||||
id: noPermissionText;
|
||||
visible: !root.canRezCertifiedItems;
|
||||
visible: !root.canRezCertifiedItems && !root.isWearable;
|
||||
text: '<font color="' + hifi.colors.redAccent + '"><a href="#">You do not have Certified Rez permissions in this domain.</a></font>'
|
||||
// Text size
|
||||
size: 16;
|
||||
|
|
|
@ -39,6 +39,7 @@ Item {
|
|||
property int itemEdition;
|
||||
property int numberSold;
|
||||
property int limitedRun;
|
||||
property bool isWearable;
|
||||
|
||||
property string originalStatusText;
|
||||
property string originalStatusColor;
|
||||
|
@ -342,7 +343,7 @@ Item {
|
|||
anchors.bottom: parent.bottom;
|
||||
anchors.right: parent.right;
|
||||
width: height;
|
||||
enabled: root.canRezCertifiedItems && root.purchaseStatus !== "invalidated";
|
||||
enabled: (root.canRezCertifiedItems || root.isWearable) && root.purchaseStatus !== "invalidated";
|
||||
|
||||
onClicked: {
|
||||
if (urlHandler.canHandleUrl(root.itemHref)) {
|
||||
|
@ -415,7 +416,7 @@ Item {
|
|||
size: 16;
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: "Rez It"
|
||||
text: root.isWearable ? "Wear It" : "Rez It"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ Rectangle {
|
|||
property bool securityImageResultReceived: false;
|
||||
property bool purchasesReceived: false;
|
||||
property bool punctuationMode: false;
|
||||
property bool canRezCertifiedItems: Entities.canRezCertified || Entities.canRezTmpCertified;
|
||||
property bool canRezCertifiedItems: Entities.canRezCertified() || Entities.canRezTmpCertified();
|
||||
property bool pendingInventoryReply: true;
|
||||
property bool isShowingMyItems: false;
|
||||
property bool isDebuggingFirstUseTutorial: false;
|
||||
|
@ -434,6 +434,7 @@ Rectangle {
|
|||
numberSold: model.number_sold;
|
||||
limitedRun: model.limited_run;
|
||||
displayedItemCount: model.displayedItemCount;
|
||||
isWearable: model.categories.indexOf("Wearables") > -1;
|
||||
anchors.topMargin: 12;
|
||||
anchors.bottomMargin: 12;
|
||||
|
||||
|
@ -582,9 +583,11 @@ Rectangle {
|
|||
|
||||
Timer {
|
||||
id: inventoryTimer;
|
||||
interval: 90000;
|
||||
interval: 4000; // Change this back to 90000 after demo
|
||||
//interval: 90000;
|
||||
onTriggered: {
|
||||
if (root.activeView === "purchasesMain" && !root.pendingInventoryReply) {
|
||||
console.log("Refreshing Purchases...");
|
||||
root.pendingInventoryReply = true;
|
||||
commerce.inventory();
|
||||
}
|
||||
|
@ -660,6 +663,8 @@ Rectangle {
|
|||
currentPurchasesModelStatus !== previousPurchasesModelStatus) {
|
||||
|
||||
purchasesModel.setProperty(i, "statusChanged", true);
|
||||
} else {
|
||||
purchasesModel.setProperty(i, "statusChanged", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ Item {
|
|||
id: root;
|
||||
z: 997;
|
||||
property bool keyboardRaised: false;
|
||||
property bool isPasswordField: false;
|
||||
property string titleBarIcon: "";
|
||||
property string titleBarText: "";
|
||||
|
||||
|
@ -202,6 +203,7 @@ Item {
|
|||
|
||||
onFocusChanged: {
|
||||
root.keyboardRaised = focus;
|
||||
root.isPasswordField = (focus && passphraseField.echoMode === TextInput.Password);
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
|
@ -209,6 +211,7 @@ Item {
|
|||
|
||||
onClicked: {
|
||||
root.keyboardRaised = true;
|
||||
root.isPasswordField = (passphraseField.echoMode === TextInput.Password);
|
||||
mouse.accepted = false;
|
||||
}
|
||||
}
|
||||
|
@ -382,6 +385,7 @@ Item {
|
|||
id: keyboard;
|
||||
raised: HMD.mounted && root.keyboardRaised;
|
||||
numeric: parent.punctuationMode;
|
||||
password: root.isPasswordField;
|
||||
anchors {
|
||||
bottom: parent.bottom;
|
||||
left: parent.left;
|
||||
|
|
|
@ -80,16 +80,18 @@ Item {
|
|||
|
||||
onFocusChanged: {
|
||||
if (focus) {
|
||||
sendSignalToWallet({method: 'walletSetup_raiseKeyboard'});
|
||||
var hidePassword = (currentPassphraseField.echoMode === TextInput.Password);
|
||||
sendSignalToWallet({method: 'walletSetup_raiseKeyboard', isPasswordField: hidePassword});
|
||||
} else if (!passphraseFieldAgain.focus) {
|
||||
sendSignalToWallet({method: 'walletSetup_lowerKeyboard'});
|
||||
sendSignalToWallet({method: 'walletSetup_lowerKeyboard', isPasswordField: false});
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent;
|
||||
onPressed: {
|
||||
sendSignalToWallet({method: 'walletSetup_raiseKeyboard'});
|
||||
var hidePassword = (currentPassphraseField.echoMode === TextInput.Password);
|
||||
sendSignalToWallet({method: 'walletSetup_raiseKeyboard', isPasswordField: hidePassword});
|
||||
mouse.accepted = false;
|
||||
}
|
||||
}
|
||||
|
@ -116,16 +118,18 @@ Item {
|
|||
MouseArea {
|
||||
anchors.fill: parent;
|
||||
onPressed: {
|
||||
sendSignalToWallet({method: 'walletSetup_raiseKeyboard'});
|
||||
var hidePassword = (passphraseField.echoMode === TextInput.Password);
|
||||
sendSignalToWallet({method: 'walletSetup_raiseKeyboard', isPasswordField: hidePassword});
|
||||
mouse.accepted = false;
|
||||
}
|
||||
}
|
||||
|
||||
onFocusChanged: {
|
||||
if (focus) {
|
||||
sendMessageToLightbox({method: 'walletSetup_raiseKeyboard'});
|
||||
var hidePassword = (passphraseField.echoMode === TextInput.Password);
|
||||
sendMessageToLightbox({method: 'walletSetup_raiseKeyboard', isPasswordField: hidePassword});
|
||||
} else if (!passphraseFieldAgain.focus) {
|
||||
sendMessageToLightbox({method: 'walletSetup_lowerKeyboard'});
|
||||
sendMessageToLightbox({method: 'walletSetup_lowerKeyboard', isPasswordField: false});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,16 +154,18 @@ Item {
|
|||
MouseArea {
|
||||
anchors.fill: parent;
|
||||
onPressed: {
|
||||
sendSignalToWallet({method: 'walletSetup_raiseKeyboard'});
|
||||
var hidePassword = (passphraseFieldAgain.echoMode === TextInput.Password);
|
||||
sendSignalToWallet({method: 'walletSetup_raiseKeyboard', isPasswordField: hidePassword});
|
||||
mouse.accepted = false;
|
||||
}
|
||||
}
|
||||
|
||||
onFocusChanged: {
|
||||
if (focus) {
|
||||
sendMessageToLightbox({method: 'walletSetup_raiseKeyboard'});
|
||||
var hidePassword = (passphraseFieldAgain.echoMode === TextInput.Password);
|
||||
sendMessageToLightbox({method: 'walletSetup_raiseKeyboard', isPasswordField: hidePassword});
|
||||
} else if (!passphraseField.focus) {
|
||||
sendMessageToLightbox({method: 'walletSetup_lowerKeyboard'});
|
||||
sendMessageToLightbox({method: 'walletSetup_lowerKeyboard', isPasswordField: false});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ Rectangle {
|
|||
|
||||
property string activeView: "initialize";
|
||||
property bool keyboardRaised: false;
|
||||
property bool isPassword: false;
|
||||
|
||||
Image {
|
||||
anchors.fill: parent;
|
||||
|
@ -181,8 +182,10 @@ Rectangle {
|
|||
}
|
||||
} else if (msg.method === 'walletSetup_raiseKeyboard') {
|
||||
root.keyboardRaised = true;
|
||||
root.isPassword = msg.isPasswordField;
|
||||
} else if (msg.method === 'walletSetup_lowerKeyboard') {
|
||||
root.keyboardRaised = false;
|
||||
root.isPassword = msg.isPasswordField;
|
||||
} else {
|
||||
sendToScript(msg);
|
||||
}
|
||||
|
@ -202,6 +205,7 @@ Rectangle {
|
|||
onSendSignalToWallet: {
|
||||
if (msg.method === 'walletSetup_raiseKeyboard') {
|
||||
root.keyboardRaised = true;
|
||||
root.isPassword = msg.isPasswordField;
|
||||
} else if (msg.method === 'walletSetup_lowerKeyboard') {
|
||||
root.keyboardRaised = false;
|
||||
} else if (msg.method === 'walletSecurity_changePassphraseCancelled') {
|
||||
|
@ -685,6 +689,7 @@ Rectangle {
|
|||
id: keyboard;
|
||||
raised: HMD.mounted && root.keyboardRaised;
|
||||
numeric: parent.punctuationMode;
|
||||
password: root.isPassword;
|
||||
anchors {
|
||||
bottom: parent.bottom;
|
||||
left: parent.left;
|
||||
|
|
|
@ -43,6 +43,7 @@ Item {
|
|||
|
||||
calculatePendingAndInvalidated();
|
||||
}
|
||||
refreshTimer.start();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,6 +118,8 @@ Item {
|
|||
historyReceived = false;
|
||||
commerce.balance();
|
||||
commerce.history();
|
||||
} else {
|
||||
refreshTimer.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -138,6 +141,17 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: refreshTimer;
|
||||
interval: 4000; // Remove this after demo?
|
||||
onTriggered: {
|
||||
console.log("Refreshing Wallet Home...");
|
||||
historyReceived = false;
|
||||
commerce.balance();
|
||||
commerce.history();
|
||||
}
|
||||
}
|
||||
|
||||
// Recent Activity
|
||||
Rectangle {
|
||||
id: recentActivityContainer;
|
||||
|
|
|
@ -5091,6 +5091,7 @@ void Application::update(float deltaTime) {
|
|||
}
|
||||
|
||||
this->updateCamera(appRenderArgs._renderArgs);
|
||||
appRenderArgs._eyeToWorld = _myCamera.getTransform();
|
||||
appRenderArgs._isStereo = false;
|
||||
|
||||
{
|
||||
|
|
|
@ -587,14 +587,16 @@ void MyAvatar::simulate(float deltaTime) {
|
|||
MovingEntitiesOperator moveOperator;
|
||||
forEachDescendant([&](SpatiallyNestablePointer object) {
|
||||
// if the queryBox has changed, tell the entity-server
|
||||
if (object->getNestableType() == NestableType::Entity && object->checkAndMaybeUpdateQueryAACube()) {
|
||||
if (object->getNestableType() == NestableType::Entity && object->updateQueryAACube()) {
|
||||
EntityItemPointer entity = std::static_pointer_cast<EntityItem>(object);
|
||||
bool success;
|
||||
AACube newCube = entity->getQueryAACube(success);
|
||||
if (success) {
|
||||
moveOperator.addEntityToMoveList(entity, newCube);
|
||||
}
|
||||
if (packetSender) {
|
||||
// send an edit packet to update the entity-server about the queryAABox. If it's an
|
||||
// avatar-entity, don't.
|
||||
if (packetSender && !entity->getClientOnly()) {
|
||||
EntityItemProperties properties = entity->getProperties();
|
||||
properties.setQueryAACubeDirty();
|
||||
properties.setLastEdited(now);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// interface/src/ui/overlays
|
||||
//
|
||||
// Created by Zander Otavka on 8/7/15.
|
||||
// Modified by Daniela Fontes on 24/10/17.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
|
@ -13,6 +14,7 @@
|
|||
|
||||
#include <Application.h>
|
||||
#include <Transform.h>
|
||||
#include "avatar/AvatarManager.h"
|
||||
|
||||
void Billboardable::setProperties(const QVariantMap& properties) {
|
||||
auto isFacingAvatar = properties["isFacingAvatar"];
|
||||
|
@ -32,10 +34,11 @@ bool Billboardable::pointTransformAtCamera(Transform& transform, glm::quat offse
|
|||
if (isFacingAvatar()) {
|
||||
glm::vec3 billboardPos = transform.getTranslation();
|
||||
glm::vec3 cameraPos = qApp->getCamera().getPosition();
|
||||
glm::vec3 look = cameraPos - billboardPos;
|
||||
float elevation = -asinf(look.y / glm::length(look));
|
||||
float azimuth = atan2f(look.x, look.z);
|
||||
glm::quat rotation(glm::vec3(elevation, azimuth, 0));
|
||||
// use the referencial from the avatar, y isn't always up
|
||||
glm::vec3 avatarUP = DependencyManager::get<AvatarManager>()->getMyAvatar()->getOrientation()*Vectors::UP;
|
||||
|
||||
glm::quat rotation(conjugate(toQuat(glm::lookAt(billboardPos, cameraPos, avatarUP))));
|
||||
|
||||
transform.setRotation(rotation);
|
||||
transform.postRotate(offsetRotation);
|
||||
return true;
|
||||
|
|
|
@ -140,8 +140,8 @@ bool ContextOverlayInterface::createOrDestroyContextOverlay(const EntityItemID&
|
|||
if (event.getID() == LEFT_HAND_HW_ID) {
|
||||
offsetAngle *= -1.0f;
|
||||
}
|
||||
contextOverlayPosition = (glm::quat(glm::radians(glm::vec3(0.0f, offsetAngle, 0.0f)))) *
|
||||
((cameraPosition + direction * (distance - CONTEXT_OVERLAY_OFFSET_DISTANCE)));
|
||||
contextOverlayPosition = cameraPosition +
|
||||
(glm::quat(glm::radians(glm::vec3(0.0f, offsetAngle, 0.0f)))) * (direction * (distance - CONTEXT_OVERLAY_OFFSET_DISTANCE));
|
||||
contextOverlayDimensions = glm::vec2(CONTEXT_OVERLAY_SIZE, CONTEXT_OVERLAY_SIZE) * glm::distance(contextOverlayPosition, cameraPosition);
|
||||
}
|
||||
|
||||
|
|
|
@ -96,6 +96,7 @@ void Line3DOverlay::setEnd(const glm::vec3& end) {
|
|||
} else {
|
||||
_direction = glm::vec3(0.0f);
|
||||
}
|
||||
notifyRenderTransformChange();
|
||||
}
|
||||
|
||||
void Line3DOverlay::setLocalEnd(const glm::vec3& localEnd) {
|
||||
|
|
|
@ -418,6 +418,19 @@ void OpenGLDisplayPlugin::customizeContext() {
|
|||
_hudPipeline = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
|
||||
{
|
||||
auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS();
|
||||
auto ps = gpu::StandardShaderLib::getDrawTextureMirroredXPS();
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
||||
gpu::Shader::makeProgram(*program);
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setDepthTest(gpu::State::DepthTest(false));
|
||||
state->setBlendFunction(true,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
_mirrorHUDPipeline = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
|
||||
{
|
||||
auto vs = gpu::StandardShaderLib::getDrawTransformUnitQuadVS();
|
||||
auto ps = gpu::StandardShaderLib::getDrawTexturePS();
|
||||
|
@ -438,6 +451,7 @@ void OpenGLDisplayPlugin::uncustomizeContext() {
|
|||
_presentPipeline.reset();
|
||||
_cursorPipeline.reset();
|
||||
_hudPipeline.reset();
|
||||
_mirrorHUDPipeline.reset();
|
||||
_compositeFramebuffer.reset();
|
||||
withPresentThreadLock([&] {
|
||||
_currentFrame.reset();
|
||||
|
@ -562,11 +576,11 @@ void OpenGLDisplayPlugin::updateFrameData() {
|
|||
});
|
||||
}
|
||||
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&)> OpenGLDisplayPlugin::getHUDOperator() {
|
||||
return [this](gpu::Batch& batch, const gpu::TexturePointer& hudTexture) {
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> OpenGLDisplayPlugin::getHUDOperator() {
|
||||
return [this](gpu::Batch& batch, const gpu::TexturePointer& hudTexture, bool mirror) {
|
||||
if (_hudPipeline) {
|
||||
batch.enableStereo(false);
|
||||
batch.setPipeline(_hudPipeline);
|
||||
batch.setPipeline(mirror ? _mirrorHUDPipeline : _hudPipeline);
|
||||
batch.setResourceTexture(0, hudTexture);
|
||||
if (isStereo()) {
|
||||
for_each_eye([&](Eye eye) {
|
||||
|
|
|
@ -95,7 +95,7 @@ protected:
|
|||
virtual QThread::Priority getPresentPriority() { return QThread::HighPriority; }
|
||||
virtual void compositeLayers();
|
||||
virtual void compositeScene();
|
||||
virtual std::function<void(gpu::Batch&, const gpu::TexturePointer&)> getHUDOperator();
|
||||
virtual std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> getHUDOperator();
|
||||
virtual void compositePointer();
|
||||
virtual void compositeExtra() {};
|
||||
|
||||
|
@ -140,6 +140,8 @@ protected:
|
|||
gpu::Frame* _lastFrame { nullptr };
|
||||
gpu::FramebufferPointer _compositeFramebuffer;
|
||||
gpu::PipelinePointer _hudPipeline;
|
||||
gpu::PipelinePointer _mirrorHUDPipeline;
|
||||
gpu::ShaderPointer _mirrorHUDPS;
|
||||
gpu::PipelinePointer _simplePipeline;
|
||||
gpu::PipelinePointer _presentPipeline;
|
||||
gpu::PipelinePointer _cursorPipeline;
|
||||
|
|
|
@ -419,9 +419,9 @@ void HmdDisplayPlugin::HUDRenderer::updatePipeline() {
|
|||
}
|
||||
}
|
||||
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&)> HmdDisplayPlugin::HUDRenderer::render(HmdDisplayPlugin& plugin) {
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> HmdDisplayPlugin::HUDRenderer::render(HmdDisplayPlugin& plugin) {
|
||||
updatePipeline();
|
||||
return [this](gpu::Batch& batch, const gpu::TexturePointer& hudTexture) {
|
||||
return [this](gpu::Batch& batch, const gpu::TexturePointer& hudTexture, bool mirror) {
|
||||
if (pipeline) {
|
||||
batch.setPipeline(pipeline);
|
||||
|
||||
|
@ -436,7 +436,11 @@ std::function<void(gpu::Batch&, const gpu::TexturePointer&)> HmdDisplayPlugin::H
|
|||
batch.setUniformBuffer(uniformsLocation, uniformsBuffer);
|
||||
|
||||
auto compositorHelper = DependencyManager::get<CompositorHelper>();
|
||||
batch.setModelTransform(compositorHelper->getUiTransform());
|
||||
glm::mat4 modelTransform = compositorHelper->getUiTransform();
|
||||
if (mirror) {
|
||||
modelTransform = glm::scale(modelTransform, glm::vec3(-1, 1, 1));
|
||||
}
|
||||
batch.setModelTransform(modelTransform);
|
||||
batch.setResourceTexture(0, hudTexture);
|
||||
|
||||
batch.drawIndexed(gpu::TRIANGLES, indexCount);
|
||||
|
@ -468,7 +472,7 @@ void HmdDisplayPlugin::compositePointer() {
|
|||
});
|
||||
}
|
||||
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&)> HmdDisplayPlugin::getHUDOperator() {
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> HmdDisplayPlugin::getHUDOperator() {
|
||||
return _hudRenderer.render(*this);
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ protected:
|
|||
|
||||
bool internalActivate() override;
|
||||
void internalDeactivate() override;
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&)> getHUDOperator() override;
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> getHUDOperator() override;
|
||||
void compositePointer() override;
|
||||
void internalPresent() override;
|
||||
void customizeContext() override;
|
||||
|
@ -116,6 +116,6 @@ private:
|
|||
|
||||
void build();
|
||||
void updatePipeline();
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&)> render(HmdDisplayPlugin& plugin);
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> render(HmdDisplayPlugin& plugin);
|
||||
} _hudRenderer;
|
||||
};
|
||||
|
|
|
@ -50,7 +50,9 @@ void EntityRenderer::initEntityRenderers() {
|
|||
REGISTER_ENTITY_TYPE_WITH_FACTORY(PolyVox, RenderablePolyVoxEntityItem::factory)
|
||||
}
|
||||
|
||||
|
||||
const Transform& EntityRenderer::getModelTransform() const {
|
||||
return _modelTransform;
|
||||
}
|
||||
|
||||
void EntityRenderer::makeStatusGetters(const EntityItemPointer& entity, Item::Status::Getters& statusGetters) {
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
|
|
|
@ -105,8 +105,10 @@ protected:
|
|||
template<typename T>
|
||||
std::shared_ptr<T> asTypedEntity() { return std::static_pointer_cast<T>(_entity); }
|
||||
|
||||
|
||||
static void makeStatusGetters(const EntityItemPointer& entity, Item::Status::Getters& statusGetters);
|
||||
static std::function<bool()> _entitiesShouldFadeFunction;
|
||||
const Transform& getModelTransform() const;
|
||||
|
||||
SharedSoundPointer _collisionSound;
|
||||
QUuid _changeHandlerId;
|
||||
|
@ -114,7 +116,6 @@ protected:
|
|||
quint64 _fadeStartTime{ usecTimestampNow() };
|
||||
bool _isFading{ _entitiesShouldFadeFunction() };
|
||||
bool _prevIsTransparent { false };
|
||||
Transform _modelTransform;
|
||||
Item::Bound _bound;
|
||||
bool _visible { false };
|
||||
bool _moving { false };
|
||||
|
@ -123,6 +124,10 @@ protected:
|
|||
|
||||
|
||||
private:
|
||||
// The base class relies on comparing the model transform to the entity transform in order
|
||||
// to trigger an update, so the member must not be visible to derived classes as a modifiable
|
||||
// transform
|
||||
Transform _modelTransform;
|
||||
// The rendering code only gets access to the entity in very specific circumstances
|
||||
// i.e. to see if the rendering code needs to update because of a change in state of the
|
||||
// entity. This forces all the rendering code itself to be independent of the entity
|
||||
|
|
|
@ -49,9 +49,10 @@ void LineEntityRenderer::doRender(RenderArgs* args) {
|
|||
PerformanceTimer perfTimer("RenderableLineEntityItem::render");
|
||||
Q_ASSERT(args->_batch);
|
||||
gpu::Batch& batch = *args->_batch;
|
||||
const auto& modelTransform = getModelTransform();
|
||||
Transform transform = Transform();
|
||||
transform.setTranslation(_modelTransform.getTranslation());
|
||||
transform.setRotation(_modelTransform.getRotation());
|
||||
transform.setTranslation(modelTransform.getTranslation());
|
||||
transform.setRotation(modelTransform.getRotation());
|
||||
batch.setModelTransform(transform);
|
||||
if (_linePoints.size() > 1) {
|
||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch);
|
||||
|
|
|
@ -695,12 +695,8 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
|
|||
void RenderableModelEntityItem::setCollisionShape(const btCollisionShape* shape) {
|
||||
const void* key = static_cast<const void*>(shape);
|
||||
if (_collisionMeshKey != key) {
|
||||
if (_collisionMeshKey) {
|
||||
collisionMeshCache.releaseMesh(_collisionMeshKey);
|
||||
}
|
||||
_collisionMeshKey = key;
|
||||
// toggle _showCollisionGeometry forces re-evaluation later
|
||||
_showCollisionGeometry = !_showCollisionGeometry;
|
||||
emit requestCollisionGeometryUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1103,6 +1099,10 @@ bool ModelEntityRenderer::needsRenderUpdate() const {
|
|||
if (model->getRenderItemsNeedUpdate()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_needsCollisionGeometryUpdate) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return Parent::needsRenderUpdate();
|
||||
}
|
||||
|
@ -1169,6 +1169,15 @@ bool ModelEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoin
|
|||
return false;
|
||||
}
|
||||
|
||||
void ModelEntityRenderer::setCollisionMeshKey(const void*key) {
|
||||
if (key != _collisionMeshKey) {
|
||||
if (_collisionMeshKey) {
|
||||
collisionMeshCache.releaseMesh(_collisionMeshKey);
|
||||
}
|
||||
_collisionMeshKey = key;
|
||||
}
|
||||
}
|
||||
|
||||
void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
||||
DETAILED_PROFILE_RANGE(simulation_physics, __FUNCTION__);
|
||||
if (_hasModel != entity->hasModel()) {
|
||||
|
@ -1201,6 +1210,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
model = std::make_shared<Model>(nullptr, entity.get());
|
||||
connect(model.get(), &Model::setURLFinished, this, &ModelEntityRenderer::requestRenderUpdate);
|
||||
connect(model.get(), &Model::requestRenderUpdate, this, &ModelEntityRenderer::requestRenderUpdate);
|
||||
connect(entity.get(), &RenderableModelEntityItem::requestCollisionGeometryUpdate, this, &ModelEntityRenderer::flagForCollisionGeometryUpdate);
|
||||
model->setLoadingPriority(EntityTreeRenderer::getEntityLoadingPriority(*entity));
|
||||
model->init();
|
||||
entity->setModel(model);
|
||||
|
@ -1259,6 +1269,26 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
}
|
||||
// TODO? early exit here when not visible?
|
||||
|
||||
if (_needsCollisionGeometryUpdate) {
|
||||
setCollisionMeshKey(entity->getCollisionMeshKey());
|
||||
_needsCollisionGeometryUpdate = false;
|
||||
ShapeType type = entity->getShapeType();
|
||||
if (_showCollisionGeometry && type != SHAPE_TYPE_STATIC_MESH && type != SHAPE_TYPE_NONE) {
|
||||
// NOTE: it is OK if _collisionMeshKey is nullptr
|
||||
model::MeshPointer mesh = collisionMeshCache.getMesh(_collisionMeshKey);
|
||||
// NOTE: the model will render the collisionGeometry if it has one
|
||||
_model->setCollisionMesh(mesh);
|
||||
} else {
|
||||
if (_collisionMeshKey) {
|
||||
// release mesh
|
||||
collisionMeshCache.releaseMesh(_collisionMeshKey);
|
||||
}
|
||||
// clear model's collision geometry
|
||||
model::MeshPointer mesh = nullptr;
|
||||
_model->setCollisionMesh(mesh);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
DETAILED_PROFILE_RANGE(simulation_physics, "Fixup");
|
||||
if (model->needsFixupInScene()) {
|
||||
|
@ -1297,6 +1327,11 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
}
|
||||
}
|
||||
|
||||
void ModelEntityRenderer::flagForCollisionGeometryUpdate() {
|
||||
_needsCollisionGeometryUpdate = true;
|
||||
emit requestRenderUpdate();
|
||||
}
|
||||
|
||||
// NOTE: this only renders the "meta" portion of the Model, namely it renders debugging items
|
||||
void ModelEntityRenderer::doRender(RenderArgs* args) {
|
||||
DETAILED_PROFILE_RANGE(render_detail, "MetaModelRender");
|
||||
|
@ -1311,7 +1346,7 @@ void ModelEntityRenderer::doRender(RenderArgs* args) {
|
|||
if (!model || (model && model->didVisualGeometryRequestFail())) {
|
||||
static glm::vec4 greenColor(0.0f, 1.0f, 0.0f, 1.0f);
|
||||
gpu::Batch& batch = *args->_batch;
|
||||
batch.setModelTransform(_modelTransform); // we want to include the scale as well
|
||||
batch.setModelTransform(getModelTransform()); // we want to include the scale as well
|
||||
DependencyManager::get<GeometryCache>()->renderWireCubeInstance(args, batch, greenColor);
|
||||
return;
|
||||
}
|
||||
|
@ -1327,28 +1362,11 @@ void ModelEntityRenderer::doRender(RenderArgs* args) {
|
|||
// Remap textures for the next frame to avoid flicker
|
||||
// remapTextures();
|
||||
|
||||
#if 0
|
||||
// update whether the model should be showing collision mesh (this may flag for fixupInScene)
|
||||
bool showingCollisionGeometry = (bool)(args->_debugFlags & (int)RenderArgs::RENDER_DEBUG_HULLS);
|
||||
if (showingCollisionGeometry != _showCollisionGeometry) {
|
||||
ShapeType type = _entity->getShapeType();
|
||||
_showCollisionGeometry = showingCollisionGeometry;
|
||||
if (_showCollisionGeometry && type != SHAPE_TYPE_STATIC_MESH && type != SHAPE_TYPE_NONE) {
|
||||
// NOTE: it is OK if _collisionMeshKey is nullptr
|
||||
model::MeshPointer mesh = collisionMeshCache.getMesh(_collisionMeshKey);
|
||||
// NOTE: the model will render the collisionGeometry if it has one
|
||||
_model->setCollisionMesh(mesh);
|
||||
} else {
|
||||
// release mesh
|
||||
if (_collisionMeshKey) {
|
||||
collisionMeshCache.releaseMesh(_collisionMeshKey);
|
||||
}
|
||||
// clear model's collision geometry
|
||||
model::MeshPointer mesh = nullptr;
|
||||
_model->setCollisionMesh(mesh);
|
||||
}
|
||||
bool showCollisionGeometry = (bool)(args->_debugFlags & (int)RenderArgs::RENDER_DEBUG_HULLS);
|
||||
if (showCollisionGeometry != _showCollisionGeometry) {
|
||||
_showCollisionGeometry = showCollisionGeometry;
|
||||
flagForCollisionGeometryUpdate();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ModelEntityRenderer::mapJoints(const TypedEntityPointer& entity, const QStringList& modelJointNames) {
|
||||
|
|
|
@ -50,6 +50,8 @@ private:
|
|||
};
|
||||
|
||||
class RenderableModelEntityItem : public ModelEntityWrapper {
|
||||
Q_OBJECT
|
||||
|
||||
friend class render::entities::ModelEntityRenderer;
|
||||
using Parent = ModelEntityWrapper;
|
||||
public:
|
||||
|
@ -105,6 +107,10 @@ public:
|
|||
virtual QStringList getJointNames() const override;
|
||||
|
||||
bool getMeshes(MeshProxyList& result) override;
|
||||
const void* getCollisionMeshKey() const { return _collisionMeshKey; }
|
||||
|
||||
signals:
|
||||
void requestCollisionGeometryUpdate();
|
||||
|
||||
private:
|
||||
bool needsUpdateModelBounds() const;
|
||||
|
@ -117,7 +123,6 @@ private:
|
|||
QVariantMap _originalTextures;
|
||||
bool _dimensionsInitialized { true };
|
||||
bool _needsJointSimulation { false };
|
||||
bool _showCollisionGeometry { false };
|
||||
const void* _collisionMeshKey { nullptr };
|
||||
};
|
||||
|
||||
|
@ -141,6 +146,8 @@ protected:
|
|||
virtual bool needsRenderUpdate() const override;
|
||||
virtual void doRender(RenderArgs* args) override;
|
||||
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;
|
||||
void flagForCollisionGeometryUpdate();
|
||||
void setCollisionMeshKey(const void* key);
|
||||
|
||||
private:
|
||||
void animate(const TypedEntityPointer& entity);
|
||||
|
@ -163,6 +170,7 @@ private:
|
|||
|
||||
bool _needsJointSimulation{ false };
|
||||
bool _showCollisionGeometry{ false };
|
||||
bool _needsCollisionGeometryUpdate{ false };
|
||||
const void* _collisionMeshKey{ nullptr };
|
||||
|
||||
// used on client side
|
||||
|
|
|
@ -69,7 +69,7 @@ ParticleEffectEntityRenderer::ParticleEffectEntityRenderer(const EntityItemPoint
|
|||
}
|
||||
|
||||
bool ParticleEffectEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const {
|
||||
entity->checkAndMaybeUpdateQueryAACube();
|
||||
entity->updateQueryAACube();
|
||||
|
||||
if (_emitting != entity->getIsEmitting()) {
|
||||
return true;
|
||||
|
@ -251,12 +251,13 @@ void ParticleEffectEntityRenderer::stepSimulation() {
|
|||
});
|
||||
|
||||
if (_emitting && particleProperties.emitting()) {
|
||||
const auto& modelTransform = getModelTransform();
|
||||
uint64_t emitInterval = particleProperties.emitIntervalUsecs();
|
||||
if (emitInterval > 0 && interval >= _timeUntilNextEmit) {
|
||||
auto timeRemaining = interval;
|
||||
while (timeRemaining > _timeUntilNextEmit) {
|
||||
// emit particle
|
||||
_cpuParticles.push_back(createParticle(now, _modelTransform, particleProperties));
|
||||
_cpuParticles.push_back(createParticle(now, modelTransform, particleProperties));
|
||||
_timeUntilNextEmit = emitInterval;
|
||||
if (emitInterval < timeRemaining) {
|
||||
timeRemaining -= emitInterval;
|
||||
|
@ -315,7 +316,7 @@ void ParticleEffectEntityRenderer::doRender(RenderArgs* args) {
|
|||
// In trail mode, the particles are created in world space.
|
||||
// so we only set a transform if they're not in trail mode
|
||||
if (!_particleProperties.emission.shouldTrail) {
|
||||
transform = _modelTransform;
|
||||
transform = getModelTransform();
|
||||
transform.setScale(vec3(1));
|
||||
}
|
||||
batch.setModelTransform(transform);
|
||||
|
|
|
@ -76,6 +76,14 @@ bool ShapeEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoin
|
|||
return true;
|
||||
}
|
||||
|
||||
if (_shape != entity->getShape()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_dimensions != entity->getDimensions()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -93,12 +101,13 @@ void ShapeEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
_position = entity->getPosition();
|
||||
_dimensions = entity->getDimensions();
|
||||
_orientation = entity->getOrientation();
|
||||
_renderTransform = getModelTransform();
|
||||
|
||||
if (_shape == entity::Sphere) {
|
||||
_modelTransform.postScale(SPHERE_ENTITY_SCALE);
|
||||
_renderTransform.postScale(SPHERE_ENTITY_SCALE);
|
||||
}
|
||||
|
||||
_modelTransform.postScale(_dimensions);
|
||||
_renderTransform.postScale(_dimensions);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -133,7 +142,7 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
|||
glm::vec4 outColor;
|
||||
withReadLock([&] {
|
||||
geometryShape = MAPPING[_shape];
|
||||
batch.setModelTransform(_modelTransform); // use a transform with scale, rotation, registration point and translation
|
||||
batch.setModelTransform(_renderTransform); // use a transform with scale, rotation, registration point and translation
|
||||
outColor = _color;
|
||||
if (_procedural.isReady()) {
|
||||
_procedural.prepare(batch, _position, _dimensions, _orientation);
|
||||
|
|
|
@ -32,6 +32,7 @@ private:
|
|||
|
||||
Procedural _procedural;
|
||||
QString _lastUserData;
|
||||
Transform _renderTransform;
|
||||
entity::Shape _shape { entity::Sphere };
|
||||
glm::vec4 _color;
|
||||
glm::vec3 _position;
|
||||
|
|
|
@ -93,10 +93,11 @@ void TextEntityRenderer::doRender(RenderArgs* args) {
|
|||
Q_ASSERT(args->_batch);
|
||||
gpu::Batch& batch = *args->_batch;
|
||||
|
||||
auto transformToTopLeft = _modelTransform;
|
||||
const auto& modelTransform = getModelTransform();
|
||||
auto transformToTopLeft = modelTransform;
|
||||
if (_faceCamera) {
|
||||
//rotate about vertical to face the camera
|
||||
glm::vec3 dPosition = args->getViewFrustum().getPosition() - _modelTransform.getTranslation();
|
||||
glm::vec3 dPosition = args->getViewFrustum().getPosition() - modelTransform.getTranslation();
|
||||
// If x and z are 0, atan(x, z) is undefined, so default to 0 degrees
|
||||
float yawRotation = dPosition.x == 0.0f && dPosition.z == 0.0f ? 0.0f : glm::atan(dPosition.x, dPosition.z);
|
||||
glm::quat orientation = glm::quat(glm::vec3(0.0f, yawRotation, 0.0f));
|
||||
|
|
|
@ -139,8 +139,8 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene
|
|||
|
||||
glm::vec2 windowSize = getWindowSize(entity);
|
||||
_webSurface->resize(QSize(windowSize.x, windowSize.y));
|
||||
|
||||
_modelTransform.postScale(entity->getDimensions());
|
||||
_renderTransform = getModelTransform();
|
||||
_renderTransform.postScale(entity->getDimensions());
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -180,7 +180,7 @@ void WebEntityRenderer::doRender(RenderArgs* args) {
|
|||
|
||||
gpu::Batch& batch = *args->_batch;
|
||||
withReadLock([&] {
|
||||
batch.setModelTransform(_modelTransform);
|
||||
batch.setModelTransform(_renderTransform);
|
||||
});
|
||||
batch.setResourceTexture(0, _texture);
|
||||
float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
|
||||
|
|
|
@ -62,6 +62,7 @@ private:
|
|||
uint16_t _lastDPI;
|
||||
QTimer _timer;
|
||||
uint64_t _lastRenderTime { 0 };
|
||||
Transform _renderTransform;
|
||||
};
|
||||
|
||||
} } // namespace
|
||||
|
|
|
@ -112,6 +112,7 @@ void ZoneEntityRenderer::doRender(RenderArgs* args) {
|
|||
// Do we need to allocate the light in the stage ?
|
||||
if (LightStage::isIndexInvalid(_sunIndex)) {
|
||||
_sunIndex = _stage->addLight(_sunLight);
|
||||
_shadowIndex = _stage->addShadow(_sunIndex);
|
||||
} else {
|
||||
_stage->updateLightArrayBuffer(_sunIndex);
|
||||
}
|
||||
|
@ -248,7 +249,8 @@ void ZoneEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scen
|
|||
|
||||
void ZoneEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||
if (entity->getShapeType() == SHAPE_TYPE_SPHERE) {
|
||||
_modelTransform.postScale(SPHERE_ENTITY_SCALE);
|
||||
_renderTransform = getModelTransform();
|
||||
_renderTransform.postScale(SPHERE_ENTITY_SCALE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -88,6 +88,7 @@ private:
|
|||
ComponentMode _hazeMode{ COMPONENT_MODE_INHERIT };
|
||||
|
||||
indexed_container::Index _sunIndex{ LightStage::INVALID_INDEX };
|
||||
indexed_container::Index _shadowIndex{ LightStage::INVALID_INDEX };
|
||||
indexed_container::Index _ambientIndex{ LightStage::INVALID_INDEX };
|
||||
|
||||
BackgroundStagePointer _backgroundStage;
|
||||
|
@ -119,6 +120,7 @@ private:
|
|||
bool _validSkyboxTexture{ false };
|
||||
|
||||
QString _proceduralUserData;
|
||||
Transform _renderTransform;
|
||||
};
|
||||
|
||||
} } // namespace
|
||||
|
|
|
@ -361,14 +361,6 @@ int EntityItem::expectedBytes() {
|
|||
|
||||
// clients use this method to unpack FULL updates from entity-server
|
||||
int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args) {
|
||||
if (args.bitstreamVersion < VERSION_ENTITIES_SUPPORT_SPLIT_MTU) {
|
||||
|
||||
// NOTE: This shouldn't happen. The only versions of the bit stream that didn't support split mtu buffers should
|
||||
// be handled by the model subclass and shouldn't call this routine.
|
||||
qCDebug(entities) << "EntityItem::readEntityDataFromBuffer()... "
|
||||
"ERROR CASE...args.bitstreamVersion < VERSION_ENTITIES_SUPPORT_SPLIT_MTU";
|
||||
return 0;
|
||||
}
|
||||
setSourceUUID(args.sourceUUID);
|
||||
|
||||
args.entitiesPerPacket++;
|
||||
|
@ -594,34 +586,32 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
|
||||
// Newer bitstreams will have a last simulated and a last updated value
|
||||
quint64 lastSimulatedFromBufferAdjusted = now;
|
||||
if (args.bitstreamVersion >= VERSION_ENTITIES_HAS_LAST_SIMULATED_TIME) {
|
||||
// last simulated is stored as ByteCountCoded delta from lastEdited
|
||||
quint64 simulatedDelta;
|
||||
parser.readCompressedCount(simulatedDelta);
|
||||
// last simulated is stored as ByteCountCoded delta from lastEdited
|
||||
quint64 simulatedDelta;
|
||||
parser.readCompressedCount(simulatedDelta);
|
||||
#ifdef VALIDATE_ENTITY_ITEM_PARSER
|
||||
{
|
||||
QByteArray encodedSimulatedDelta = originalDataBuffer.mid(bytesRead); // maximum possible size
|
||||
ByteCountCoded<quint64> simulatedDeltaCoder = encodedSimulatedDelta;
|
||||
quint64 simulatedDelta2 = simulatedDeltaCoder;
|
||||
Q_ASSERT(simulatedDelta2 == simulatedDelta);
|
||||
encodedSimulatedDelta = simulatedDeltaCoder; // determine true length
|
||||
dataAt += encodedSimulatedDelta.size();
|
||||
bytesRead += encodedSimulatedDelta.size();
|
||||
Q_ASSERT(parser.offset() == (unsigned int) bytesRead);
|
||||
}
|
||||
{
|
||||
QByteArray encodedSimulatedDelta = originalDataBuffer.mid(bytesRead); // maximum possible size
|
||||
ByteCountCoded<quint64> simulatedDeltaCoder = encodedSimulatedDelta;
|
||||
quint64 simulatedDelta2 = simulatedDeltaCoder;
|
||||
Q_ASSERT(simulatedDelta2 == simulatedDelta);
|
||||
encodedSimulatedDelta = simulatedDeltaCoder; // determine true length
|
||||
dataAt += encodedSimulatedDelta.size();
|
||||
bytesRead += encodedSimulatedDelta.size();
|
||||
Q_ASSERT(parser.offset() == (unsigned int) bytesRead);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (overwriteLocalData) {
|
||||
lastSimulatedFromBufferAdjusted = lastEditedFromBufferAdjusted + simulatedDelta; // don't adjust for clock skew since we already did that
|
||||
if (lastSimulatedFromBufferAdjusted > now) {
|
||||
lastSimulatedFromBufferAdjusted = now;
|
||||
}
|
||||
#ifdef WANT_DEBUG
|
||||
qCDebug(entities) << " _lastEdited:" << debugTime(_lastEdited, now);
|
||||
qCDebug(entities) << " lastEditedFromBufferAdjusted:" << debugTime(lastEditedFromBufferAdjusted, now);
|
||||
qCDebug(entities) << " lastSimulatedFromBufferAdjusted:" << debugTime(lastSimulatedFromBufferAdjusted, now);
|
||||
#endif
|
||||
if (overwriteLocalData) {
|
||||
lastSimulatedFromBufferAdjusted = lastEditedFromBufferAdjusted + simulatedDelta; // don't adjust for clock skew since we already did that
|
||||
if (lastSimulatedFromBufferAdjusted > now) {
|
||||
lastSimulatedFromBufferAdjusted = now;
|
||||
}
|
||||
#ifdef WANT_DEBUG
|
||||
qCDebug(entities) << " _lastEdited:" << debugTime(_lastEdited, now);
|
||||
qCDebug(entities) << " lastEditedFromBufferAdjusted:" << debugTime(lastEditedFromBufferAdjusted, now);
|
||||
qCDebug(entities) << " lastSimulatedFromBufferAdjusted:" << debugTime(lastSimulatedFromBufferAdjusted, now);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef WANT_DEBUG
|
||||
|
@ -723,6 +713,14 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
weOwnSimulation = _simulationOwner.matchesValidID(myNodeID);
|
||||
}
|
||||
}
|
||||
|
||||
auto lastEdited = lastEditedFromBufferAdjusted;
|
||||
bool otherOverwrites = overwriteLocalData && !weOwnSimulation;
|
||||
auto shouldUpdate = [lastEdited, otherOverwrites, filterRejection](quint64 updatedTimestamp, bool valueChanged) {
|
||||
bool simulationChanged = lastEdited > updatedTimestamp;
|
||||
return otherOverwrites && simulationChanged && (valueChanged || filterRejection);
|
||||
};
|
||||
|
||||
{ // When we own the simulation we don't accept updates to the entity's transform/velocities
|
||||
// we also want to ignore any duplicate packets that have the same "recently updated" values
|
||||
// as a packet we've already recieved. This is because we want multiple edits of the same
|
||||
|
@ -735,15 +733,9 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
|
||||
// Note: duplicate packets are expected and not wrong. They may be sent for any number of
|
||||
// reasons and the contract is that the client handles them in an idempotent manner.
|
||||
auto lastEdited = lastEditedFromBufferAdjusted;
|
||||
bool otherOverwrites = overwriteLocalData && !weOwnSimulation;
|
||||
auto shouldUpdate = [lastEdited, otherOverwrites, filterRejection](quint64 updatedTimestamp, bool valueChanged) {
|
||||
bool simulationChanged = lastEdited > updatedTimestamp;
|
||||
return otherOverwrites && simulationChanged && (valueChanged || filterRejection);
|
||||
};
|
||||
auto customUpdatePositionFromNetwork = [this, shouldUpdate, lastEdited](glm::vec3 value){
|
||||
if (shouldUpdate(_lastUpdatedPositionTimestamp, value != _lastUpdatedPositionValue)) {
|
||||
updatePositionFromNetwork(value);
|
||||
updatePosition(value);
|
||||
_lastUpdatedPositionTimestamp = lastEdited;
|
||||
_lastUpdatedPositionValue = value;
|
||||
}
|
||||
|
@ -751,7 +743,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
|
||||
auto customUpdateRotationFromNetwork = [this, shouldUpdate, lastEdited](glm::quat value){
|
||||
if (shouldUpdate(_lastUpdatedRotationTimestamp, value != _lastUpdatedRotationValue)) {
|
||||
updateRotationFromNetwork(value);
|
||||
updateRotation(value);
|
||||
_lastUpdatedRotationTimestamp = lastEdited;
|
||||
_lastUpdatedRotationValue = value;
|
||||
}
|
||||
|
@ -759,7 +751,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
|
||||
auto customUpdateVelocityFromNetwork = [this, shouldUpdate, lastEdited](glm::vec3 value){
|
||||
if (shouldUpdate(_lastUpdatedVelocityTimestamp, value != _lastUpdatedVelocityValue)) {
|
||||
updateVelocityFromNetwork(value);
|
||||
updateVelocity(value);
|
||||
_lastUpdatedVelocityTimestamp = lastEdited;
|
||||
_lastUpdatedVelocityValue = value;
|
||||
}
|
||||
|
@ -767,7 +759,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
|
||||
auto customUpdateAngularVelocityFromNetwork = [this, shouldUpdate, lastEdited](glm::vec3 value){
|
||||
if (shouldUpdate(_lastUpdatedAngularVelocityTimestamp, value != _lastUpdatedAngularVelocityValue)) {
|
||||
updateAngularVelocityFromNetwork(value);
|
||||
updateAngularVelocity(value);
|
||||
_lastUpdatedAngularVelocityTimestamp = lastEdited;
|
||||
_lastUpdatedAngularVelocityValue = value;
|
||||
}
|
||||
|
@ -786,8 +778,6 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
READ_ENTITY_PROPERTY(PROP_VELOCITY, glm::vec3, customUpdateVelocityFromNetwork);
|
||||
READ_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, glm::vec3, customUpdateAngularVelocityFromNetwork);
|
||||
READ_ENTITY_PROPERTY(PROP_ACCELERATION, glm::vec3, customSetAcceleration);
|
||||
|
||||
|
||||
}
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_DIMENSIONS, glm::vec3, updateDimensions);
|
||||
|
@ -823,20 +813,16 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
READ_ENTITY_PROPERTY(PROP_LOCKED, bool, updateLocked);
|
||||
READ_ENTITY_PROPERTY(PROP_USER_DATA, QString, setUserData);
|
||||
|
||||
if (args.bitstreamVersion >= VERSION_ENTITIES_HAS_MARKETPLACE_ID) {
|
||||
READ_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, QString, setMarketplaceID);
|
||||
}
|
||||
if (args.bitstreamVersion >= VERSION_ENTITIES_HAS_CERTIFICATE_PROPERTIES) {
|
||||
READ_ENTITY_PROPERTY(PROP_ITEM_NAME, QString, setItemName);
|
||||
READ_ENTITY_PROPERTY(PROP_ITEM_DESCRIPTION, QString, setItemDescription);
|
||||
READ_ENTITY_PROPERTY(PROP_ITEM_CATEGORIES, QString, setItemCategories);
|
||||
READ_ENTITY_PROPERTY(PROP_ITEM_ARTIST, QString, setItemArtist);
|
||||
READ_ENTITY_PROPERTY(PROP_ITEM_LICENSE, QString, setItemLicense);
|
||||
READ_ENTITY_PROPERTY(PROP_LIMITED_RUN, quint32, setLimitedRun);
|
||||
READ_ENTITY_PROPERTY(PROP_EDITION_NUMBER, quint32, setEditionNumber);
|
||||
READ_ENTITY_PROPERTY(PROP_ENTITY_INSTANCE_NUMBER, quint32, setEntityInstanceNumber);
|
||||
READ_ENTITY_PROPERTY(PROP_CERTIFICATE_ID, QString, setCertificateID);
|
||||
}
|
||||
READ_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, QString, setMarketplaceID);
|
||||
READ_ENTITY_PROPERTY(PROP_ITEM_NAME, QString, setItemName);
|
||||
READ_ENTITY_PROPERTY(PROP_ITEM_DESCRIPTION, QString, setItemDescription);
|
||||
READ_ENTITY_PROPERTY(PROP_ITEM_CATEGORIES, QString, setItemCategories);
|
||||
READ_ENTITY_PROPERTY(PROP_ITEM_ARTIST, QString, setItemArtist);
|
||||
READ_ENTITY_PROPERTY(PROP_ITEM_LICENSE, QString, setItemLicense);
|
||||
READ_ENTITY_PROPERTY(PROP_LIMITED_RUN, quint32, setLimitedRun);
|
||||
READ_ENTITY_PROPERTY(PROP_EDITION_NUMBER, quint32, setEditionNumber);
|
||||
READ_ENTITY_PROPERTY(PROP_ENTITY_INSTANCE_NUMBER, quint32, setEntityInstanceNumber);
|
||||
READ_ENTITY_PROPERTY(PROP_CERTIFICATE_ID, QString, setCertificateID);
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_NAME, QString, setName);
|
||||
READ_ENTITY_PROPERTY(PROP_COLLISION_SOUND_URL, QString, setCollisionSoundURL);
|
||||
|
@ -852,7 +838,18 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
overwriteLocalData = oldOverwrite;
|
||||
}
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_QUERY_AA_CUBE, AACube, setQueryAACube);
|
||||
|
||||
{
|
||||
auto customUpdateQueryAACubeFromNetwork = [this, shouldUpdate, lastEdited](AACube value){
|
||||
if (shouldUpdate(_lastUpdatedQueryAACubeTimestamp, value != _lastUpdatedQueryAACubeValue)) {
|
||||
setQueryAACube(value);
|
||||
_lastUpdatedQueryAACubeTimestamp = lastEdited;
|
||||
_lastUpdatedQueryAACubeValue = value;
|
||||
}
|
||||
};
|
||||
READ_ENTITY_PROPERTY(PROP_QUERY_AA_CUBE, AACube, customUpdateQueryAACubeFromNetwork);
|
||||
}
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_LAST_EDITED_BY, QUuid, setLastEditedBy);
|
||||
|
||||
bytesRead += readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args,
|
||||
|
@ -864,10 +861,6 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
// NOTE: we had a bad version of the stream that we added stream data after the subclass. We can attempt to recover
|
||||
// by doing this parsing here... but it's not likely going to fully recover the content.
|
||||
//
|
||||
// TODO: Remove this code once we've sufficiently migrated content past this damaged version
|
||||
if (args.bitstreamVersion == VERSION_ENTITIES_HAS_MARKETPLACE_ID_DAMAGED) {
|
||||
READ_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, QString, setMarketplaceID);
|
||||
}
|
||||
|
||||
if (overwriteLocalData && (getDirtyFlags() & (Simulation::DIRTY_TRANSFORM | Simulation::DIRTY_VELOCITIES))) {
|
||||
// NOTE: This code is attempting to "repair" the old data we just got from the server to make it more
|
||||
|
@ -1387,8 +1380,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) {
|
|||
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(lastEditedBy, setLastEditedBy);
|
||||
|
||||
AACube saveQueryAACube = _queryAACube;
|
||||
if (checkAndMaybeUpdateQueryAACube() && saveQueryAACube != _queryAACube) {
|
||||
if (updateQueryAACube()) {
|
||||
somethingChanged = true;
|
||||
}
|
||||
|
||||
|
@ -1552,6 +1544,9 @@ AACube EntityItem::getQueryAACube(bool& success) const {
|
|||
return result;
|
||||
}
|
||||
|
||||
bool EntityItem::shouldPuffQueryAACube() const {
|
||||
return hasActions() || isChildOfMyAvatar() || isMovingRelativeToParent();
|
||||
}
|
||||
|
||||
// NOTE: This should only be used in cases of old bitstreams which only contain radius data
|
||||
// 0,0,0 --> maxDimension,maxDimension,maxDimension
|
||||
|
@ -1765,16 +1760,10 @@ void EntityItem::updateParentID(const QUuid& value) {
|
|||
if (tree) {
|
||||
tree->addToNeedsParentFixupList(getThisPointer());
|
||||
}
|
||||
updateQueryAACube();
|
||||
}
|
||||
}
|
||||
|
||||
void EntityItem::updatePositionFromNetwork(const glm::vec3& value) {
|
||||
if (shouldSuppressLocationEdits()) {
|
||||
return;
|
||||
}
|
||||
updatePosition(value);
|
||||
}
|
||||
|
||||
void EntityItem::updateDimensions(const glm::vec3& value) {
|
||||
if (getDimensions() != value) {
|
||||
setDimensions(value);
|
||||
|
@ -1797,13 +1786,6 @@ void EntityItem::updateRotation(const glm::quat& rotation) {
|
|||
}
|
||||
}
|
||||
|
||||
void EntityItem::updateRotationFromNetwork(const glm::quat& rotation) {
|
||||
if (shouldSuppressLocationEdits()) {
|
||||
return;
|
||||
}
|
||||
updateRotation(rotation);
|
||||
}
|
||||
|
||||
void EntityItem::updateMass(float mass) {
|
||||
// Setting the mass actually changes the _density (at fixed volume), however
|
||||
// we must protect the density range to help maintain stability of physics simulation
|
||||
|
@ -1854,13 +1836,6 @@ void EntityItem::updateVelocity(const glm::vec3& value) {
|
|||
}
|
||||
}
|
||||
|
||||
void EntityItem::updateVelocityFromNetwork(const glm::vec3& value) {
|
||||
if (shouldSuppressLocationEdits()) {
|
||||
return;
|
||||
}
|
||||
updateVelocity(value);
|
||||
}
|
||||
|
||||
void EntityItem::updateDamping(float value) {
|
||||
auto clampedDamping = glm::clamp(value, 0.0f, 1.0f);
|
||||
if (_damping != clampedDamping) {
|
||||
|
@ -1912,13 +1887,6 @@ void EntityItem::updateAngularVelocity(const glm::vec3& value) {
|
|||
}
|
||||
}
|
||||
|
||||
void EntityItem::updateAngularVelocityFromNetwork(const glm::vec3& value) {
|
||||
if (shouldSuppressLocationEdits()) {
|
||||
return;
|
||||
}
|
||||
updateAngularVelocity(value);
|
||||
}
|
||||
|
||||
void EntityItem::updateAngularDamping(float value) {
|
||||
auto clampedDamping = glm::clamp(value, 0.0f, 1.0f);
|
||||
if (_angularDamping != clampedDamping) {
|
||||
|
@ -2031,9 +1999,7 @@ void EntityItem::computeCollisionGroupAndFinalMask(int16_t& group, int16_t& mask
|
|||
// if this entity is a descendant of MyAvatar, don't collide with MyAvatar. This avoids the
|
||||
// "bootstrapping" problem where you can shoot yourself across the room by grabbing something
|
||||
// and holding it against your own avatar.
|
||||
QUuid ancestorID = findAncestorOfType(NestableType::Avatar);
|
||||
if (!ancestorID.isNull() &&
|
||||
(ancestorID == Physics::getSessionUUID() || ancestorID == AVATAR_SELF_ID)) {
|
||||
if (isChildOfMyAvatar()) {
|
||||
iAmHoldingThis = true;
|
||||
}
|
||||
// also, don't bootstrap our own avatar with a hold action
|
||||
|
@ -2140,6 +2106,7 @@ bool EntityItem::addAction(EntitySimulationPointer simulation, EntityDynamicPoin
|
|||
removeActionInternal(action->getID());
|
||||
}
|
||||
});
|
||||
updateQueryAACube();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -2198,6 +2165,8 @@ bool EntityItem::removeAction(EntitySimulationPointer simulation, const QUuid& a
|
|||
checkWaitingToRemove(simulation);
|
||||
success = removeActionInternal(actionID);
|
||||
});
|
||||
updateQueryAACube();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
@ -2440,6 +2409,7 @@ QVariantMap EntityItem::getActionArguments(const QUuid& actionID) const {
|
|||
}
|
||||
|
||||
bool EntityItem::shouldSuppressLocationEdits() const {
|
||||
// if any of the actions indicate they'd like suppression, suppress
|
||||
QHash<QUuid, EntityDynamicPointer>::const_iterator i = _objectActions.begin();
|
||||
while (i != _objectActions.end()) {
|
||||
if (i.value()->shouldSuppressLocationEdits()) {
|
||||
|
@ -2448,6 +2418,11 @@ bool EntityItem::shouldSuppressLocationEdits() const {
|
|||
i++;
|
||||
}
|
||||
|
||||
// if any of the ancestors are MyAvatar, suppress
|
||||
if (isChildOfMyAvatar()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2852,6 +2827,11 @@ void EntityItem::setVisible(bool value) {
|
|||
});
|
||||
}
|
||||
|
||||
bool EntityItem::isChildOfMyAvatar() const {
|
||||
QUuid ancestorID = findAncestorOfType(NestableType::Avatar);
|
||||
return !ancestorID.isNull() && (ancestorID == Physics::getSessionUUID() || ancestorID == AVATAR_SELF_ID);
|
||||
}
|
||||
|
||||
bool EntityItem::getCollisionless() const {
|
||||
bool result;
|
||||
withReadLock([&] {
|
||||
|
|
|
@ -237,6 +237,7 @@ public:
|
|||
|
||||
using SpatiallyNestable::getQueryAACube;
|
||||
virtual AACube getQueryAACube(bool& success) const override;
|
||||
virtual bool shouldPuffQueryAACube() const override;
|
||||
|
||||
QString getScript() const;
|
||||
void setScript(const QString& value);
|
||||
|
@ -270,6 +271,8 @@ public:
|
|||
inline bool isVisible() const { return getVisible(); }
|
||||
inline bool isInvisible() const { return !getVisible(); }
|
||||
|
||||
bool isChildOfMyAvatar() const;
|
||||
|
||||
bool getCollisionless() const;
|
||||
void setCollisionless(bool value);
|
||||
|
||||
|
@ -348,20 +351,16 @@ public:
|
|||
virtual void updateRegistrationPoint(const glm::vec3& value);
|
||||
void updatePosition(const glm::vec3& value);
|
||||
void updateParentID(const QUuid& value);
|
||||
void updatePositionFromNetwork(const glm::vec3& value);
|
||||
void updateDimensions(const glm::vec3& value);
|
||||
void updateRotation(const glm::quat& rotation);
|
||||
void updateRotationFromNetwork(const glm::quat& rotation);
|
||||
void updateDensity(float value);
|
||||
void updateMass(float value);
|
||||
void updateVelocity(const glm::vec3& value);
|
||||
void updateVelocityFromNetwork(const glm::vec3& value);
|
||||
void updateDamping(float value);
|
||||
void updateRestitution(float value);
|
||||
void updateFriction(float value);
|
||||
void updateGravity(const glm::vec3& value);
|
||||
void updateAngularVelocity(const glm::vec3& value);
|
||||
void updateAngularVelocityFromNetwork(const glm::vec3& value);
|
||||
void updateAngularDamping(float value);
|
||||
void updateCollisionless(bool value);
|
||||
void updateCollisionMask(uint8_t value);
|
||||
|
@ -626,12 +625,15 @@ protected:
|
|||
glm::vec3 _lastUpdatedVelocityValue;
|
||||
glm::vec3 _lastUpdatedAngularVelocityValue;
|
||||
glm::vec3 _lastUpdatedAccelerationValue;
|
||||
AACube _lastUpdatedQueryAACubeValue;
|
||||
|
||||
quint64 _lastUpdatedPositionTimestamp { 0 };
|
||||
quint64 _lastUpdatedRotationTimestamp { 0 };
|
||||
quint64 _lastUpdatedVelocityTimestamp { 0 };
|
||||
quint64 _lastUpdatedAngularVelocityTimestamp { 0 };
|
||||
quint64 _lastUpdatedAccelerationTimestamp { 0 };
|
||||
quint64 _lastUpdatedQueryAACubeTimestamp { 0 };
|
||||
|
||||
};
|
||||
|
||||
#endif // hifi_EntityItem_h
|
||||
|
|
|
@ -50,6 +50,10 @@ EntityScriptingInterface::EntityScriptingInterface(bool bidOnSimulationOwnership
|
|||
connect(nodeList.data(), &NodeList::canRezCertifiedChanged, this, &EntityScriptingInterface::canRezCertifiedChanged);
|
||||
connect(nodeList.data(), &NodeList::canRezTmpCertifiedChanged, this, &EntityScriptingInterface::canRezTmpCertifiedChanged);
|
||||
connect(nodeList.data(), &NodeList::canWriteAssetsChanged, this, &EntityScriptingInterface::canWriteAssetsChanged);
|
||||
|
||||
|
||||
auto& packetReceiver = nodeList->getPacketReceiver();
|
||||
packetReceiver.registerListener(PacketType::EntityScriptCallMethod, this, "handleEntityScriptCallMethodPacket");
|
||||
}
|
||||
|
||||
void EntityScriptingInterface::queueEntityMessage(PacketType packetType,
|
||||
|
@ -457,7 +461,7 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties&
|
|||
// if they've changed.
|
||||
entity->forEachDescendant([&](SpatiallyNestablePointer descendant) {
|
||||
if (descendant->getNestableType() == NestableType::Entity) {
|
||||
if (descendant->checkAndMaybeUpdateQueryAACube()) {
|
||||
if (descendant->updateQueryAACube()) {
|
||||
EntityItemPointer entityDescendant = std::static_pointer_cast<EntityItem>(descendant);
|
||||
EntityItemProperties newQueryCubeProperties;
|
||||
newQueryCubeProperties.setQueryAACube(descendant->getQueryAACube());
|
||||
|
@ -571,6 +575,48 @@ void EntityScriptingInterface::callEntityServerMethod(QUuid id, const QString& m
|
|||
DependencyManager::get<EntityScriptClient>()->callEntityServerMethod(id, method, params);
|
||||
}
|
||||
|
||||
void EntityScriptingInterface::callEntityClientMethod(QUuid clientSessionID, QUuid entityID, const QString& method, const QStringList& params) {
|
||||
PROFILE_RANGE(script_entities, __FUNCTION__);
|
||||
auto scriptServerServices = DependencyManager::get<EntityScriptServerServices>();
|
||||
|
||||
// this won't be available on clients
|
||||
if (scriptServerServices) {
|
||||
scriptServerServices->callEntityClientMethod(clientSessionID, entityID, method, params);
|
||||
} else {
|
||||
qWarning() << "Entities.callEntityClientMethod() not allowed in client";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EntityScriptingInterface::handleEntityScriptCallMethodPacket(QSharedPointer<ReceivedMessage> receivedMessage, SharedNodePointer senderNode) {
|
||||
PROFILE_RANGE(script_entities, __FUNCTION__);
|
||||
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
SharedNodePointer entityScriptServer = nodeList->soloNodeOfType(NodeType::EntityScriptServer);
|
||||
|
||||
if (entityScriptServer == senderNode) {
|
||||
auto entityID = QUuid::fromRfc4122(receivedMessage->read(NUM_BYTES_RFC4122_UUID));
|
||||
|
||||
auto method = receivedMessage->readString();
|
||||
|
||||
quint16 paramCount;
|
||||
receivedMessage->readPrimitive(¶mCount);
|
||||
|
||||
QStringList params;
|
||||
for (int param = 0; param < paramCount; param++) {
|
||||
auto paramString = receivedMessage->readString();
|
||||
params << paramString;
|
||||
}
|
||||
|
||||
std::lock_guard<std::recursive_mutex> lock(_entitiesScriptEngineLock);
|
||||
if (_entitiesScriptEngine) {
|
||||
_entitiesScriptEngine->callEntityScriptMethod(entityID, method, params, senderNode->getUUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
QUuid EntityScriptingInterface::findClosestEntity(const glm::vec3& center, float radius) const {
|
||||
PROFILE_RANGE(script_entities, __FUNCTION__);
|
||||
|
||||
|
|
|
@ -189,12 +189,15 @@ public slots:
|
|||
Q_INVOKABLE void deleteEntity(QUuid entityID);
|
||||
|
||||
/**jsdoc
|
||||
* Call a method on an entity. Allows a script to call a method on an entity's script.
|
||||
* The method will execute in the entity script engine. If the entity does not have an
|
||||
* entity script or the method does not exist, this call will have no effect.
|
||||
* If it is running an entity script (specified by the `script` property)
|
||||
* Call a method on an entity in the same context as this function is called. Allows a script
|
||||
* to call a method on an entity's script. The method will execute in the entity script engine.
|
||||
* If the entity does not have an entity script or the method does not exist, this call will
|
||||
* have no effect. If it is running an entity script (specified by the `script` property)
|
||||
* and it exposes a property with the specified name `method`, it will be called
|
||||
* using `params` as the list of arguments.
|
||||
* using `params` as the list of arguments. If this is called within an entity script, the
|
||||
* method will be executed on the client in the entity script engine in which it was called. If
|
||||
* this is called in an entity server script, the method will be executed on the entity server
|
||||
* script engine.
|
||||
*
|
||||
* @function Entities.callEntityMethod
|
||||
* @param {EntityID} entityID The ID of the entity to call the method on.
|
||||
|
@ -218,6 +221,21 @@ public slots:
|
|||
*/
|
||||
Q_INVOKABLE void callEntityServerMethod(QUuid entityID, const QString& method, const QStringList& params = QStringList());
|
||||
|
||||
/**jsdoc
|
||||
* Call a client method on an entity on a specific client node. Allows a server entity script to call a
|
||||
* method on an entity's client script for a particular client. The method will execute in the entity script
|
||||
* engine on that single client. If the entity does not have an entity script or the method does not exist, or
|
||||
* the client is not connected to the domain, or you attempt to make this call outside of the entity server
|
||||
* script, this call will have no effect.
|
||||
*
|
||||
* @function Entities.callEntityClientMethod
|
||||
* @param {SessionID} clientSessionID The session ID of the client to call the method on.
|
||||
* @param {EntityID} entityID The ID of the entity to call the method on.
|
||||
* @param {string} method The name of the method to call.
|
||||
* @param {string[]} params The list of parameters to call the specified method with.
|
||||
*/
|
||||
Q_INVOKABLE void callEntityClientMethod(QUuid clientSessionID, QUuid entityID, const QString& method, const QStringList& params = QStringList());
|
||||
|
||||
/**jsdoc
|
||||
* finds the closest model to the center point, within the radius
|
||||
* will return a EntityItemID.isKnownID = false if no models are in the radius
|
||||
|
@ -444,6 +462,10 @@ protected:
|
|||
std::lock_guard<std::recursive_mutex> lock(_entitiesScriptEngineLock);
|
||||
function(_entitiesScriptEngine);
|
||||
};
|
||||
|
||||
private slots:
|
||||
void handleEntityScriptCallMethodPacket(QSharedPointer<ReceivedMessage> receivedMessage, SharedNodePointer senderNode);
|
||||
|
||||
private:
|
||||
bool actionWorker(const QUuid& entityID, std::function<bool(EntitySimulationPointer, EntityItemPointer)> actor);
|
||||
bool polyVoxWorker(QUuid entityID, std::function<bool(PolyVoxEntityItem&)> actor);
|
||||
|
|
|
@ -1074,7 +1074,8 @@ void EntityTree::fixupTerseEditLogging(EntityItemProperties& properties, QList<Q
|
|||
changedProperties[index] = QString("queryAACube:") +
|
||||
QString::number((int)center.x) + "," +
|
||||
QString::number((int)center.y) + "," +
|
||||
QString::number((int)center.z);
|
||||
QString::number((int)center.z) + "/" +
|
||||
QString::number(properties.getQueryAACube().getDimensions().x);
|
||||
}
|
||||
if (properties.positionChanged()) {
|
||||
int index = changedProperties.indexOf("position");
|
||||
|
@ -2066,7 +2067,7 @@ QVector<EntityItemID> EntityTree::sendEntities(EntityEditPacketSender* packetSen
|
|||
addToNeedsParentFixupList(entity);
|
||||
}
|
||||
entity->forceQueryAACubeUpdate();
|
||||
entity->checkAndMaybeUpdateQueryAACube();
|
||||
entity->updateQueryAACube();
|
||||
moveOperator.addEntityToMoveList(entity, entity->getQueryAACube());
|
||||
i++;
|
||||
} else {
|
||||
|
|
|
@ -89,8 +89,6 @@ public:
|
|||
// own definition. Implement these to allow your octree based server to support editing
|
||||
virtual bool getWantSVOfileVersions() const override { return true; }
|
||||
virtual PacketType expectedDataPacketType() const override { return PacketType::EntityData; }
|
||||
virtual bool canProcessVersion(PacketVersion thisVersion) const override
|
||||
{ return thisVersion >= VERSION_ENTITIES_USE_METERS_AND_RADIANS; }
|
||||
virtual bool handlesEditPacketType(PacketType packetType) const override;
|
||||
void fixupTerseEditLogging(EntityItemProperties& properties, QList<QString>& changedProperties);
|
||||
virtual int processEditPacketData(ReceivedMessage& message, const unsigned char* editData, int maxLength,
|
||||
|
@ -112,9 +110,6 @@ public:
|
|||
virtual void releaseSceneEncodeData(OctreeElementExtraEncodeData* extraEncodeData) const override;
|
||||
virtual bool mustIncludeAllChildData() const override { return false; }
|
||||
|
||||
virtual bool versionHasSVOfileBreaks(PacketVersion thisVersion) const override
|
||||
{ return thisVersion >= VERSION_ENTITIES_HAS_FILE_BREAKS; }
|
||||
|
||||
virtual void update() override { update(true); }
|
||||
|
||||
void update(bool simulate);
|
||||
|
|
|
@ -102,12 +102,6 @@ EntityItemPointer EntityTypes::constructEntityItem(EntityType entityType, const
|
|||
EntityItemPointer EntityTypes::constructEntityItem(const unsigned char* data, int bytesToRead,
|
||||
ReadBitstreamToTreeParams& args) {
|
||||
|
||||
if (args.bitstreamVersion < VERSION_ENTITIES_SUPPORT_SPLIT_MTU) {
|
||||
EntityItemID tempEntityID;
|
||||
EntityItemProperties tempProperties;
|
||||
return constructEntityItem(Model, tempEntityID, tempProperties);
|
||||
}
|
||||
|
||||
// Header bytes
|
||||
// object ID [16 bytes]
|
||||
// ByteCountCoded(type code) [~1 byte]
|
||||
|
|
|
@ -175,35 +175,12 @@ int LightEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
int bytesRead = 0;
|
||||
const unsigned char* dataAt = data;
|
||||
|
||||
if (args.bitstreamVersion < VERSION_ENTITIES_LIGHT_HAS_INTENSITY_AND_COLOR_PROPERTIES) {
|
||||
READ_ENTITY_PROPERTY(PROP_IS_SPOTLIGHT, bool, setIsSpotlight);
|
||||
|
||||
// _diffuseColor has been renamed to _color
|
||||
READ_ENTITY_PROPERTY(PROP_DIFFUSE_COLOR, rgbColor, setColor);
|
||||
|
||||
// Ambient and specular color are from an older format and are no longer supported.
|
||||
// Their values will be ignored.
|
||||
READ_ENTITY_PROPERTY(PROP_AMBIENT_COLOR_UNUSED, rgbColor, setIgnoredColor);
|
||||
READ_ENTITY_PROPERTY(PROP_SPECULAR_COLOR_UNUSED, rgbColor, setIgnoredColor);
|
||||
|
||||
// _constantAttenuation has been renamed to _intensity
|
||||
READ_ENTITY_PROPERTY(PROP_INTENSITY, float, setIntensity);
|
||||
|
||||
// Linear and quadratic attenuation are from an older format and are no longer supported.
|
||||
// Their values will be ignored.
|
||||
READ_ENTITY_PROPERTY(PROP_LINEAR_ATTENUATION_UNUSED, float, setIgnoredAttenuation);
|
||||
READ_ENTITY_PROPERTY(PROP_QUADRATIC_ATTENUATION_UNUSED, float, setIgnoredAttenuation);
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_EXPONENT, float, setExponent);
|
||||
READ_ENTITY_PROPERTY(PROP_CUTOFF, float, setCutoff);
|
||||
} else {
|
||||
READ_ENTITY_PROPERTY(PROP_IS_SPOTLIGHT, bool, setIsSpotlight);
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR, rgbColor, setColor);
|
||||
READ_ENTITY_PROPERTY(PROP_INTENSITY, float, setIntensity);
|
||||
READ_ENTITY_PROPERTY(PROP_EXPONENT, float, setExponent);
|
||||
READ_ENTITY_PROPERTY(PROP_CUTOFF, float, setCutoff);
|
||||
READ_ENTITY_PROPERTY(PROP_FALLOFF_RADIUS, float, setFalloffRadius);
|
||||
}
|
||||
READ_ENTITY_PROPERTY(PROP_IS_SPOTLIGHT, bool, setIsSpotlight);
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR, rgbColor, setColor);
|
||||
READ_ENTITY_PROPERTY(PROP_INTENSITY, float, setIntensity);
|
||||
READ_ENTITY_PROPERTY(PROP_EXPONENT, float, setExponent);
|
||||
READ_ENTITY_PROPERTY(PROP_CUTOFF, float, setCutoff);
|
||||
READ_ENTITY_PROPERTY(PROP_FALLOFF_RADIUS, float, setFalloffRadius);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
|
|
@ -111,38 +111,19 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR, rgbColor, setColor);
|
||||
READ_ENTITY_PROPERTY(PROP_MODEL_URL, QString, setModelURL);
|
||||
if (args.bitstreamVersion < VERSION_ENTITIES_HAS_COLLISION_MODEL) {
|
||||
setCompoundShapeURL("");
|
||||
} else {
|
||||
READ_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, QString, setCompoundShapeURL);
|
||||
}
|
||||
|
||||
// Because we're using AnimationLoop which will reset the frame index if you change it's running state
|
||||
// we want to read these values in the order they appear in the buffer, but call our setters in an
|
||||
// order that allows AnimationLoop to preserve the correct frame rate.
|
||||
if (args.bitstreamVersion < VERSION_ENTITIES_ANIMATION_PROPERTIES_GROUP) {
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_URL, QString, setAnimationURL);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_FPS, float, setAnimationFPS);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, float, setAnimationCurrentFrame);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, bool, setAnimationIsPlaying);
|
||||
}
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, QString, setCompoundShapeURL);
|
||||
READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures);
|
||||
|
||||
if (args.bitstreamVersion < VERSION_ENTITIES_ANIMATION_PROPERTIES_GROUP) {
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, QString, setAnimationSettings);
|
||||
} else {
|
||||
int bytesFromAnimation;
|
||||
withWriteLock([&] {
|
||||
// Note: since we've associated our _animationProperties with our _animationLoop, the readEntitySubclassDataFromBuffer()
|
||||
// will automatically read into the animation loop
|
||||
bytesFromAnimation = _animationProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args,
|
||||
propertyFlags, overwriteLocalData, animationPropertiesChanged);
|
||||
});
|
||||
int bytesFromAnimation;
|
||||
withWriteLock([&] {
|
||||
// Note: since we've associated our _animationProperties with our _animationLoop, the readEntitySubclassDataFromBuffer()
|
||||
// will automatically read into the animation loop
|
||||
bytesFromAnimation = _animationProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args,
|
||||
propertyFlags, overwriteLocalData, animationPropertiesChanged);
|
||||
});
|
||||
|
||||
bytesRead += bytesFromAnimation;
|
||||
dataAt += bytesFromAnimation;
|
||||
}
|
||||
bytesRead += bytesFromAnimation;
|
||||
dataAt += bytesFromAnimation;
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, setShapeType);
|
||||
|
||||
|
|
|
@ -464,76 +464,40 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch
|
|||
const unsigned char* dataAt = data;
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR, rgbColor, setColor);
|
||||
// Because we're using AnimationLoop which will reset the frame index if you change it's running state
|
||||
// we want to read these values in the order they appear in the buffer, but call our setters in an
|
||||
// order that allows AnimationLoop to preserve the correct frame rate.
|
||||
if (args.bitstreamVersion < VERSION_ENTITIES_ANIMATION_PROPERTIES_GROUP) {
|
||||
SKIP_ENTITY_PROPERTY(PROP_ANIMATION_FPS, float);
|
||||
SKIP_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, float);
|
||||
SKIP_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, bool);
|
||||
SKIP_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, QString);
|
||||
} else {
|
||||
READ_ENTITY_PROPERTY(PROP_EMITTING_PARTICLES, bool, setIsEmitting);
|
||||
}
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_EMITTING_PARTICLES, bool, setIsEmitting);
|
||||
READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, setShapeType);
|
||||
READ_ENTITY_PROPERTY(PROP_MAX_PARTICLES, quint32, setMaxParticles);
|
||||
READ_ENTITY_PROPERTY(PROP_LIFESPAN, float, setLifespan);
|
||||
READ_ENTITY_PROPERTY(PROP_EMIT_RATE, float, setEmitRate);
|
||||
if (args.bitstreamVersion < VERSION_ENTITIES_PARTICLE_ELLIPSOID_EMITTER) {
|
||||
// OLD PROP_EMIT_VELOCITY FAKEOUT
|
||||
SKIP_ENTITY_PROPERTY(PROP_EMIT_SPEED, glm::vec3);
|
||||
}
|
||||
|
||||
if (args.bitstreamVersion >= VERSION_ENTITIES_PARTICLE_MODIFICATIONS) {
|
||||
READ_ENTITY_PROPERTY(PROP_EMIT_ACCELERATION, glm::vec3, setEmitAcceleration);
|
||||
READ_ENTITY_PROPERTY(PROP_ACCELERATION_SPREAD, glm::vec3, setAccelerationSpread);
|
||||
READ_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float, setParticleRadius);
|
||||
READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures);
|
||||
if (args.bitstreamVersion < VERSION_ENTITIES_PARTICLE_ELLIPSOID_EMITTER) {
|
||||
// OLD PROP_VELOCITY_SPREAD FAKEOUT
|
||||
SKIP_ENTITY_PROPERTY(PROP_SPEED_SPREAD, glm::vec3);
|
||||
}
|
||||
} else {
|
||||
// OLD PROP_EMIT_ACCELERATION FAKEOUT
|
||||
SKIP_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float);
|
||||
// OLD PROP_ACCELERATION_SPREAD FAKEOUT
|
||||
SKIP_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float);
|
||||
READ_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float, setParticleRadius);
|
||||
READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures);
|
||||
}
|
||||
READ_ENTITY_PROPERTY(PROP_EMIT_ACCELERATION, glm::vec3, setEmitAcceleration);
|
||||
READ_ENTITY_PROPERTY(PROP_ACCELERATION_SPREAD, glm::vec3, setAccelerationSpread);
|
||||
READ_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float, setParticleRadius);
|
||||
READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures);
|
||||
|
||||
if (args.bitstreamVersion >= VERSION_ENTITIES_PARTICLE_RADIUS_PROPERTIES) {
|
||||
READ_ENTITY_PROPERTY(PROP_RADIUS_SPREAD, float, setRadiusSpread);
|
||||
READ_ENTITY_PROPERTY(PROP_RADIUS_START, float, setRadiusStart);
|
||||
READ_ENTITY_PROPERTY(PROP_RADIUS_FINISH, float, setRadiusFinish);
|
||||
}
|
||||
READ_ENTITY_PROPERTY(PROP_RADIUS_SPREAD, float, setRadiusSpread);
|
||||
READ_ENTITY_PROPERTY(PROP_RADIUS_START, float, setRadiusStart);
|
||||
READ_ENTITY_PROPERTY(PROP_RADIUS_FINISH, float, setRadiusFinish);
|
||||
|
||||
if (args.bitstreamVersion >= VERSION_ENTITIES_PARTICLE_COLOR_PROPERTIES) {
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR_SPREAD, xColor, setColorSpread);
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR_START, xColor, setColorStart);
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR_FINISH, xColor, setColorFinish);
|
||||
READ_ENTITY_PROPERTY(PROP_ALPHA, float, setAlpha);
|
||||
READ_ENTITY_PROPERTY(PROP_ALPHA_SPREAD, float, setAlphaSpread);
|
||||
READ_ENTITY_PROPERTY(PROP_ALPHA_START, float, setAlphaStart);
|
||||
READ_ENTITY_PROPERTY(PROP_ALPHA_FINISH, float, setAlphaFinish);
|
||||
}
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR_SPREAD, xColor, setColorSpread);
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR_START, xColor, setColorStart);
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR_FINISH, xColor, setColorFinish);
|
||||
READ_ENTITY_PROPERTY(PROP_ALPHA, float, setAlpha);
|
||||
READ_ENTITY_PROPERTY(PROP_ALPHA_SPREAD, float, setAlphaSpread);
|
||||
READ_ENTITY_PROPERTY(PROP_ALPHA_START, float, setAlphaStart);
|
||||
READ_ENTITY_PROPERTY(PROP_ALPHA_FINISH, float, setAlphaFinish);
|
||||
|
||||
if (args.bitstreamVersion >= VERSION_ENTITIES_PARTICLE_ELLIPSOID_EMITTER) {
|
||||
READ_ENTITY_PROPERTY(PROP_EMIT_SPEED, float, setEmitSpeed);
|
||||
READ_ENTITY_PROPERTY(PROP_SPEED_SPREAD, float, setSpeedSpread);
|
||||
READ_ENTITY_PROPERTY(PROP_EMIT_ORIENTATION, glm::quat, setEmitOrientation);
|
||||
READ_ENTITY_PROPERTY(PROP_EMIT_DIMENSIONS, glm::vec3, setEmitDimensions);
|
||||
READ_ENTITY_PROPERTY(PROP_EMIT_RADIUS_START, float, setEmitRadiusStart);
|
||||
READ_ENTITY_PROPERTY(PROP_POLAR_START, float, setPolarStart);
|
||||
READ_ENTITY_PROPERTY(PROP_POLAR_FINISH, float, setPolarFinish);
|
||||
READ_ENTITY_PROPERTY(PROP_AZIMUTH_START, float, setAzimuthStart);
|
||||
READ_ENTITY_PROPERTY(PROP_AZIMUTH_FINISH, float, setAzimuthFinish);
|
||||
}
|
||||
READ_ENTITY_PROPERTY(PROP_EMIT_SPEED, float, setEmitSpeed);
|
||||
READ_ENTITY_PROPERTY(PROP_SPEED_SPREAD, float, setSpeedSpread);
|
||||
READ_ENTITY_PROPERTY(PROP_EMIT_ORIENTATION, glm::quat, setEmitOrientation);
|
||||
READ_ENTITY_PROPERTY(PROP_EMIT_DIMENSIONS, glm::vec3, setEmitDimensions);
|
||||
READ_ENTITY_PROPERTY(PROP_EMIT_RADIUS_START, float, setEmitRadiusStart);
|
||||
READ_ENTITY_PROPERTY(PROP_POLAR_START, float, setPolarStart);
|
||||
READ_ENTITY_PROPERTY(PROP_POLAR_FINISH, float, setPolarFinish);
|
||||
READ_ENTITY_PROPERTY(PROP_AZIMUTH_START, float, setAzimuthStart);
|
||||
READ_ENTITY_PROPERTY(PROP_AZIMUTH_FINISH, float, setAzimuthFinish);
|
||||
|
||||
if (args.bitstreamVersion >= VERSION_ENTITIES_PARTICLES_ADDITIVE_BLENDING) {
|
||||
READ_ENTITY_PROPERTY(PROP_EMITTER_SHOULD_TRAIL, bool, setEmitterShouldTrail);
|
||||
}
|
||||
READ_ENTITY_PROPERTY(PROP_EMITTER_SHOULD_TRAIL, bool, setEmitterShouldTrail);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
|
|
@ -136,7 +136,7 @@ void SimpleEntitySimulation::sortEntitiesThatMoved() {
|
|||
SetOfEntities::iterator itemItr = _entitiesToSort.begin();
|
||||
while (itemItr != _entitiesToSort.end()) {
|
||||
EntityItemPointer entity = *itemItr;
|
||||
entity->checkAndMaybeUpdateQueryAACube();
|
||||
entity->updateQueryAACube();
|
||||
++itemItr;
|
||||
}
|
||||
EntitySimulation::sortEntitiesThatMoved();
|
||||
|
|
22
libraries/gpu/src/gpu/DrawTextureMirroredX.slf
Normal file
22
libraries/gpu/src/gpu/DrawTextureMirroredX.slf
Normal file
|
@ -0,0 +1,22 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// Draw texture 0 fetched at (1.0 - texcoord.x, texcoord.y)
|
||||
//
|
||||
// Created by Sam Gondelman on 10/24/2017
|
||||
// Copyright 2017 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
|
||||
//
|
||||
|
||||
|
||||
uniform sampler2D colorMap;
|
||||
|
||||
in vec2 varTexCoord0;
|
||||
out vec4 outFragColor;
|
||||
|
||||
void main(void) {
|
||||
outFragColor = texture(colorMap, vec2(1.0 - varTexCoord0.x, varTexCoord0.y));
|
||||
}
|
|
@ -23,6 +23,7 @@ const char DrawNada_frag[] = "void main(void) {}"; // DrawNada is really simple.
|
|||
|
||||
#include "DrawWhite_frag.h"
|
||||
#include "DrawTexture_frag.h"
|
||||
#include "DrawTextureMirroredX_frag.h"
|
||||
#include "DrawTextureOpaque_frag.h"
|
||||
#include "DrawColoredTexture_frag.h"
|
||||
|
||||
|
@ -37,6 +38,7 @@ ShaderPointer StandardShaderLib::_drawTransformVertexPositionVS;
|
|||
ShaderPointer StandardShaderLib::_drawNadaPS;
|
||||
ShaderPointer StandardShaderLib::_drawWhitePS;
|
||||
ShaderPointer StandardShaderLib::_drawTexturePS;
|
||||
ShaderPointer StandardShaderLib::_drawTextureMirroredXPS;
|
||||
ShaderPointer StandardShaderLib::_drawTextureOpaquePS;
|
||||
ShaderPointer StandardShaderLib::_drawColoredTexturePS;
|
||||
StandardShaderLib::ProgramMap StandardShaderLib::_programs;
|
||||
|
@ -130,6 +132,13 @@ ShaderPointer StandardShaderLib::getDrawTexturePS() {
|
|||
return _drawTexturePS;
|
||||
}
|
||||
|
||||
ShaderPointer StandardShaderLib::getDrawTextureMirroredXPS() {
|
||||
if (!_drawTextureMirroredXPS) {
|
||||
_drawTextureMirroredXPS = gpu::Shader::createPixel(std::string(DrawTextureMirroredX_frag));
|
||||
}
|
||||
return _drawTextureMirroredXPS;
|
||||
}
|
||||
|
||||
ShaderPointer StandardShaderLib::getDrawTextureOpaquePS() {
|
||||
if (!_drawTextureOpaquePS) {
|
||||
_drawTextureOpaquePS = gpu::Shader::createPixel(std::string(DrawTextureOpaque_frag));
|
||||
|
|
|
@ -47,6 +47,7 @@ public:
|
|||
|
||||
static ShaderPointer getDrawWhitePS();
|
||||
static ShaderPointer getDrawTexturePS();
|
||||
static ShaderPointer getDrawTextureMirroredXPS();
|
||||
static ShaderPointer getDrawTextureOpaquePS();
|
||||
static ShaderPointer getDrawColoredTexturePS();
|
||||
|
||||
|
@ -67,6 +68,7 @@ protected:
|
|||
static ShaderPointer _drawNadaPS;
|
||||
static ShaderPointer _drawWhitePS;
|
||||
static ShaderPointer _drawTexturePS;
|
||||
static ShaderPointer _drawTextureMirroredXPS;
|
||||
static ShaderPointer _drawTextureOpaquePS;
|
||||
static ShaderPointer _drawColoredTexturePS;
|
||||
|
||||
|
|
|
@ -92,6 +92,28 @@ void EntityScriptClient::callEntityServerMethod(QUuid entityID, const QString& m
|
|||
}
|
||||
}
|
||||
|
||||
void EntityScriptServerServices::callEntityClientMethod(QUuid clientSessionID, QUuid entityID, const QString& method, const QStringList& params) {
|
||||
// only valid to call this function if you are the entity script server
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
SharedNodePointer targetClient = nodeList->nodeWithUUID(clientSessionID);
|
||||
|
||||
if (nodeList->getOwnerType() == NodeType::EntityScriptServer && targetClient) {
|
||||
auto packetList = NLPacketList::create(PacketType::EntityScriptCallMethod, QByteArray(), true, true);
|
||||
|
||||
packetList->write(entityID.toRfc4122());
|
||||
|
||||
packetList->writeString(method);
|
||||
|
||||
quint16 paramCount = params.length();
|
||||
packetList->writePrimitive(paramCount);
|
||||
|
||||
foreach(const QString& param, params) {
|
||||
packetList->writeString(param);
|
||||
}
|
||||
|
||||
nodeList->sendPacketList(std::move(packetList), *targetClient);
|
||||
}
|
||||
}
|
||||
|
||||
MessageID EntityScriptClient::getEntityServerScriptStatus(QUuid entityID, GetScriptStatusCallback callback) {
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
|
|
|
@ -74,4 +74,11 @@ private:
|
|||
void forceFailureOfPendingRequests(SharedNodePointer node);
|
||||
};
|
||||
|
||||
|
||||
class EntityScriptServerServices : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
public:
|
||||
void callEntityClientMethod(QUuid clientSessionID, QUuid entityID, const QString& method, const QStringList& params);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -30,7 +30,8 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
|||
case PacketType::EntityEdit:
|
||||
case PacketType::EntityData:
|
||||
case PacketType::EntityPhysics:
|
||||
return VERSION_ENTITIES_HAS_DYNAMIC_OWNERSHIP_TESTS;
|
||||
return static_cast<PacketVersion>(EntityVersion::HasDynamicOwnershipTests);
|
||||
|
||||
case PacketType::EntityQuery:
|
||||
return static_cast<PacketVersion>(EntityQueryPacketVersion::JSONFilterWithFamilyTree);
|
||||
case PacketType::AvatarIdentity:
|
||||
|
@ -61,6 +62,9 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
|||
case PacketType::DomainServerAddedNode:
|
||||
return static_cast<PacketVersion>(DomainServerAddedNodeVersion::PermissionsGrid);
|
||||
|
||||
case PacketType::EntityScriptCallMethod:
|
||||
return static_cast<PacketVersion>(EntityScriptCallMethodVersion::ClientCallable);
|
||||
|
||||
case PacketType::MixedAudio:
|
||||
case PacketType::SilentAudioFrame:
|
||||
case PacketType::InjectAudio:
|
||||
|
|
|
@ -194,86 +194,15 @@ void sendWrongProtocolVersionsSignature(bool sendWrongVersion); /// for debuggin
|
|||
uint qHash(const PacketType& key, uint seed);
|
||||
QDebug operator<<(QDebug debug, const PacketType& type);
|
||||
|
||||
const PacketVersion VERSION_OCTREE_HAS_FILE_BREAKS = 1;
|
||||
const PacketVersion VERSION_ENTITIES_HAVE_ANIMATION = 1;
|
||||
const PacketVersion VERSION_ROOT_ELEMENT_HAS_DATA = 2;
|
||||
const PacketVersion VERSION_ENTITIES_SUPPORT_SPLIT_MTU = 3;
|
||||
const PacketVersion VERSION_ENTITIES_HAS_FILE_BREAKS = VERSION_ENTITIES_SUPPORT_SPLIT_MTU;
|
||||
const PacketVersion VERSION_ENTITIES_SUPPORT_DIMENSIONS = 4;
|
||||
const PacketVersion VERSION_ENTITIES_MODELS_HAVE_ANIMATION_SETTINGS = 5;
|
||||
const PacketVersion VERSION_ENTITIES_HAVE_USER_DATA = 6;
|
||||
const PacketVersion VERSION_ENTITIES_HAS_LAST_SIMULATED_TIME = 7;
|
||||
const PacketVersion VERSION_MODEL_ENTITIES_SUPPORT_SHAPE_TYPE = 8;
|
||||
const PacketVersion VERSION_ENTITIES_LIGHT_HAS_INTENSITY_AND_COLOR_PROPERTIES = 9;
|
||||
const PacketVersion VERSION_ENTITIES_HAS_PARTICLES = 10;
|
||||
const PacketVersion VERSION_ENTITIES_USE_METERS_AND_RADIANS = 11;
|
||||
const PacketVersion VERSION_ENTITIES_HAS_COLLISION_MODEL = 12;
|
||||
const PacketVersion VERSION_ENTITIES_HAS_MARKETPLACE_ID_DAMAGED = 13;
|
||||
const PacketVersion VERSION_ENTITIES_HAS_MARKETPLACE_ID = 14;
|
||||
const PacketVersion VERSION_ENTITIES_HAVE_ACCELERATION = 15;
|
||||
const PacketVersion VERSION_ENTITIES_HAVE_UUIDS = 16;
|
||||
const PacketVersion VERSION_ENTITIES_ZONE_ENTITIES_EXIST = 17;
|
||||
const PacketVersion VERSION_ENTITIES_ZONE_ENTITIES_HAVE_DYNAMIC_SHAPE = 18;
|
||||
const PacketVersion VERSION_ENTITIES_HAVE_NAMES = 19;
|
||||
const PacketVersion VERSION_ENTITIES_ZONE_ENTITIES_HAVE_ATMOSPHERE = 20;
|
||||
const PacketVersion VERSION_ENTITIES_ZONE_ENTITIES_HAVE_SKYBOX = 21;
|
||||
const PacketVersion VERSION_ENTITIES_ZONE_ENTITIES_STAGE_HAS_AUTOMATIC_HOURDAY = 22;
|
||||
const PacketVersion VERSION_ENTITIES_PARTICLE_ENTITIES_HAVE_TEXTURES = 23;
|
||||
const PacketVersion VERSION_ENTITIES_HAVE_LINE_TYPE = 24;
|
||||
const PacketVersion VERSION_ENTITIES_HAVE_COLLISION_SOUND_URL = 25;
|
||||
const PacketVersion VERSION_ENTITIES_HAVE_FRICTION = 26;
|
||||
const PacketVersion VERSION_NO_ENTITY_ID_SWAP = 27;
|
||||
const PacketVersion VERSION_ENTITIES_PARTICLE_FIX = 28;
|
||||
const PacketVersion VERSION_ENTITIES_LINE_POINTS = 29;
|
||||
const PacketVersion VERSION_ENTITIES_FACE_CAMERA = 30;
|
||||
const PacketVersion VERSION_ENTITIES_SCRIPT_TIMESTAMP = 31;
|
||||
const PacketVersion VERSION_ENTITIES_SCRIPT_TIMESTAMP_FIX = 32;
|
||||
const PacketVersion VERSION_ENTITIES_HAVE_SIMULATION_OWNER_AND_ACTIONS_OVER_WIRE = 33;
|
||||
const PacketVersion VERSION_ENTITIES_NEW_PROTOCOL_LAYER = 35;
|
||||
const PacketVersion VERSION_POLYVOX_TEXTURES = 36;
|
||||
const PacketVersion VERSION_ENTITIES_POLYLINE = 37;
|
||||
const PacketVersion VERSION_OCTREE_CENTERED_ORIGIN = 38;
|
||||
const PacketVersion VERSION_ENTITIES_PARTICLE_MODIFICATIONS = 39;
|
||||
const PacketVersion VERSION_ENTITIES_POLYVOX_NEIGHBORS = 40;
|
||||
const PacketVersion VERSION_ENTITIES_PARTICLE_RADIUS_PROPERTIES = 41;
|
||||
const PacketVersion VERSION_ENTITIES_PARTICLE_COLOR_PROPERTIES = 42;
|
||||
const PacketVersion VERSION_ENTITIES_PROTOCOL_HEADER_SWAP = 43;
|
||||
const PacketVersion VERSION_ENTITIES_PARTICLE_ELLIPSOID_EMITTER = 44;
|
||||
const PacketVersion VERSION_ENTITIES_PROTOCOL_CHANNELS = 45;
|
||||
const PacketVersion VERSION_ENTITIES_ANIMATION_PROPERTIES_GROUP = 46;
|
||||
const PacketVersion VERSION_ENTITIES_KEYLIGHT_PROPERTIES_GROUP = 47;
|
||||
const PacketVersion VERSION_ENTITIES_KEYLIGHT_PROPERTIES_GROUP_BIS = 48;
|
||||
const PacketVersion VERSION_ENTITIES_PARTICLES_ADDITIVE_BLENDING = 49;
|
||||
const PacketVersion VERSION_ENTITIES_POLYLINE_TEXTURE = 50;
|
||||
const PacketVersion VERSION_ENTITIES_HAVE_PARENTS = 51;
|
||||
const PacketVersion VERSION_ENTITIES_REMOVED_START_AUTOMATICALLY_FROM_ANIMATION_PROPERTY_GROUP = 52;
|
||||
const PacketVersion VERSION_MODEL_ENTITIES_JOINTS_ON_WIRE = 53;
|
||||
const PacketVersion VERSION_ENTITITES_HAVE_QUERY_BOX = 54;
|
||||
const PacketVersion VERSION_ENTITITES_HAVE_COLLISION_MASK = 55;
|
||||
const PacketVersion VERSION_ATMOSPHERE_REMOVED = 56;
|
||||
const PacketVersion VERSION_LIGHT_HAS_FALLOFF_RADIUS = 57;
|
||||
const PacketVersion VERSION_ENTITIES_NO_FLY_ZONES = 58;
|
||||
const PacketVersion VERSION_ENTITIES_MORE_SHAPES = 59;
|
||||
const PacketVersion VERSION_ENTITIES_PROPERLY_ENCODE_SHAPE_EDITS = 60;
|
||||
const PacketVersion VERSION_MODEL_ENTITIES_SUPPORT_STATIC_MESH = 61;
|
||||
const PacketVersion VERSION_MODEL_ENTITIES_SUPPORT_SIMPLE_HULLS = 62;
|
||||
const PacketVersion VERSION_WEB_ENTITIES_SUPPORT_DPI = 63;
|
||||
const PacketVersion VERSION_ENTITIES_ARROW_ACTION = 64;
|
||||
const PacketVersion VERSION_ENTITIES_LAST_EDITED_BY = 65;
|
||||
const PacketVersion VERSION_ENTITIES_SERVER_SCRIPTS = 66;
|
||||
const PacketVersion VERSION_ENTITIES_PHYSICS_PACKET = 67;
|
||||
const PacketVersion VERSION_ENTITIES_ZONE_FILTERS = 68;
|
||||
const PacketVersion VERSION_ENTITIES_HINGE_CONSTRAINT = 69;
|
||||
const PacketVersion VERSION_ENTITIES_BULLET_DYNAMICS = 70;
|
||||
const PacketVersion VERSION_ENTITIES_HAS_SHOULD_HIGHLIGHT = 71;
|
||||
const PacketVersion VERSION_ENTITIES_HAS_HIGHLIGHT_SCRIPTING_INTERFACE = 72;
|
||||
const PacketVersion VERSION_ENTITIES_ANIMATION_ALLOW_TRANSLATION_PROPERTIES = 73;
|
||||
const PacketVersion VERSION_ENTITIES_HAS_CERTIFICATE_PROPERTIES = 74;
|
||||
const PacketVersion VERSION_ENTITIES_HAZE = 75;
|
||||
const PacketVersion VERSION_ENTITIES_UV_MODE_PROPERTY = 76;
|
||||
const PacketVersion VERSION_ENTITIES_STROKE_COLOR_PROPERTY = 77;
|
||||
const PacketVersion VERSION_ENTITIES_HAS_DYNAMIC_OWNERSHIP_TESTS = 78;
|
||||
enum class EntityVersion : PacketVersion {
|
||||
StrokeColorProperty = 77,
|
||||
HasDynamicOwnershipTests
|
||||
};
|
||||
|
||||
enum class EntityScriptCallMethodVersion : PacketVersion {
|
||||
ServerCallable = 18,
|
||||
ClientCallable = 19
|
||||
};
|
||||
|
||||
enum class EntityQueryPacketVersion: PacketVersion {
|
||||
JSONFilter = 18,
|
||||
|
|
|
@ -1721,8 +1721,8 @@ bool Octree::readFromStream(uint64_t streamLength, QDataStream& inputStream, con
|
|||
device->ungetChar(firstChar);
|
||||
|
||||
if (firstChar == (char) PacketType::EntityData) {
|
||||
qCDebug(octree) << "Reading from binary SVO Stream length:" << streamLength;
|
||||
return readSVOFromStream(streamLength, inputStream);
|
||||
qCWarning(octree) << "Reading from binary SVO no longer supported";
|
||||
return false;
|
||||
} else {
|
||||
qCDebug(octree) << "Reading from JSON SVO Stream length:" << streamLength;
|
||||
return readJSONFromStream(streamLength, inputStream, marketplaceID);
|
||||
|
@ -1730,137 +1730,6 @@ bool Octree::readFromStream(uint64_t streamLength, QDataStream& inputStream, con
|
|||
}
|
||||
|
||||
|
||||
bool Octree::readSVOFromStream(uint64_t streamLength, QDataStream& inputStream) {
|
||||
qWarning() << "SVO file format depricated. Support for reading SVO files is no longer support and will be removed soon.";
|
||||
|
||||
bool fileOk = false;
|
||||
|
||||
PacketVersion gotVersion = 0;
|
||||
|
||||
uint64_t headerLength = 0; // bytes in the header
|
||||
|
||||
bool wantImportProgress = true;
|
||||
|
||||
PacketType expectedType = expectedDataPacketType();
|
||||
PacketVersion expectedVersion = versionForPacketType(expectedType);
|
||||
bool hasBufferBreaks = versionHasSVOfileBreaks(expectedVersion);
|
||||
|
||||
// before reading the file, check to see if this version of the Octree supports file versions
|
||||
if (getWantSVOfileVersions()) {
|
||||
|
||||
// read just enough of the file to parse the header...
|
||||
const uint64_t HEADER_LENGTH = sizeof(int) + sizeof(PacketVersion);
|
||||
unsigned char fileHeader[HEADER_LENGTH];
|
||||
inputStream.readRawData((char*)&fileHeader, HEADER_LENGTH);
|
||||
|
||||
headerLength = HEADER_LENGTH; // we need this later to skip to the data
|
||||
|
||||
unsigned char* dataAt = (unsigned char*)&fileHeader;
|
||||
uint64_t dataLength = HEADER_LENGTH;
|
||||
|
||||
// if so, read the first byte of the file and see if it matches the expected version code
|
||||
int intPacketType;
|
||||
memcpy(&intPacketType, dataAt, sizeof(intPacketType));
|
||||
PacketType gotType = (PacketType) intPacketType;
|
||||
|
||||
dataAt += sizeof(expectedType);
|
||||
dataLength -= sizeof(expectedType);
|
||||
gotVersion = *dataAt;
|
||||
|
||||
if (gotType == expectedType) {
|
||||
if (canProcessVersion(gotVersion)) {
|
||||
dataAt += sizeof(gotVersion);
|
||||
dataLength -= sizeof(gotVersion);
|
||||
fileOk = true;
|
||||
qCDebug(octree, "SVO file version match. Expected: %d Got: %d",
|
||||
versionForPacketType(expectedDataPacketType()), gotVersion);
|
||||
|
||||
hasBufferBreaks = versionHasSVOfileBreaks(gotVersion);
|
||||
} else {
|
||||
qCDebug(octree, "SVO file version mismatch. Expected: %d Got: %d",
|
||||
versionForPacketType(expectedDataPacketType()), gotVersion);
|
||||
}
|
||||
} else {
|
||||
qCDebug(octree) << "SVO file type mismatch. Expected: " << expectedType
|
||||
<< " Got: " << gotType;
|
||||
}
|
||||
|
||||
} else {
|
||||
qCDebug(octree) << " NOTE: this file type does not include type and version information.";
|
||||
fileOk = true; // assume the file is ok
|
||||
}
|
||||
|
||||
if (hasBufferBreaks) {
|
||||
qCDebug(octree) << " this version includes buffer breaks";
|
||||
} else {
|
||||
qCDebug(octree) << " this version does not include buffer breaks";
|
||||
}
|
||||
|
||||
if (fileOk) {
|
||||
|
||||
// if this version of the file does not include buffer breaks, then we need to load the entire file at once
|
||||
if (!hasBufferBreaks) {
|
||||
|
||||
// read the entire file into a buffer, WHAT!? Why not.
|
||||
uint64_t dataLength = streamLength - headerLength;
|
||||
unsigned char* entireFileDataSection = new unsigned char[dataLength];
|
||||
inputStream.readRawData((char*)entireFileDataSection, dataLength);
|
||||
|
||||
unsigned char* dataAt = entireFileDataSection;
|
||||
|
||||
ReadBitstreamToTreeParams args(NO_EXISTS_BITS, NULL, 0,
|
||||
SharedNodePointer(), wantImportProgress, gotVersion);
|
||||
|
||||
readBitstreamToTree(dataAt, dataLength, args);
|
||||
delete[] entireFileDataSection;
|
||||
|
||||
} else {
|
||||
|
||||
|
||||
uint64_t dataLength = streamLength - headerLength;
|
||||
uint64_t remainingLength = dataLength;
|
||||
const uint64_t MAX_CHUNK_LENGTH = MAX_OCTREE_PACKET_SIZE * 2;
|
||||
unsigned char* fileChunk = new unsigned char[MAX_CHUNK_LENGTH];
|
||||
|
||||
while (remainingLength > 0) {
|
||||
quint16 chunkLength = 0;
|
||||
|
||||
inputStream.readRawData((char*)&chunkLength, sizeof(chunkLength));
|
||||
remainingLength -= sizeof(chunkLength);
|
||||
|
||||
if (chunkLength > remainingLength) {
|
||||
qCDebug(octree) << "UNEXPECTED chunk size of:" << chunkLength
|
||||
<< "greater than remaining length:" << remainingLength;
|
||||
break;
|
||||
}
|
||||
|
||||
if (chunkLength > MAX_CHUNK_LENGTH) {
|
||||
qCDebug(octree) << "UNEXPECTED chunk size of:" << chunkLength
|
||||
<< "greater than MAX_CHUNK_LENGTH:" << MAX_CHUNK_LENGTH;
|
||||
break;
|
||||
}
|
||||
|
||||
inputStream.readRawData((char*)fileChunk, chunkLength);
|
||||
|
||||
remainingLength -= chunkLength;
|
||||
|
||||
unsigned char* dataAt = fileChunk;
|
||||
uint64_t dataLength = chunkLength;
|
||||
|
||||
ReadBitstreamToTreeParams args(NO_EXISTS_BITS, NULL, 0,
|
||||
SharedNodePointer(), wantImportProgress, gotVersion);
|
||||
|
||||
readBitstreamToTree(dataAt, dataLength, args);
|
||||
}
|
||||
|
||||
delete[] fileChunk;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return fileOk;
|
||||
}
|
||||
|
||||
// hack to get the marketplace id into the entities. We will create a way to get this from a hash of
|
||||
// the entity later, but this helps us move things along for now
|
||||
QJsonDocument addMarketplaceIDToDocumentEntities(QJsonDocument& doc, const QString& marketplaceID) {
|
||||
|
|
|
@ -208,8 +208,6 @@ public:
|
|||
// own definition. Implement these to allow your octree based server to support editing
|
||||
virtual bool getWantSVOfileVersions() const { return false; }
|
||||
virtual PacketType expectedDataPacketType() const { return PacketType::Unknown; }
|
||||
virtual bool canProcessVersion(PacketVersion thisVersion) const {
|
||||
return thisVersion == versionForPacketType(expectedDataPacketType()); }
|
||||
virtual PacketVersion expectedVersion() const { return versionForPacketType(expectedDataPacketType()); }
|
||||
virtual bool handlesEditPacketType(PacketType packetType) const { return false; }
|
||||
virtual int processEditPacketData(ReceivedMessage& message, const unsigned char* editData, int maxLength,
|
||||
|
@ -223,11 +221,6 @@ public:
|
|||
virtual void releaseSceneEncodeData(OctreeElementExtraEncodeData* extraEncodeData) const { }
|
||||
virtual bool mustIncludeAllChildData() const { return true; }
|
||||
|
||||
/// some versions of the SVO file will include breaks with buffer lengths between each buffer chunk in the SVO
|
||||
/// file. If the Octree subclass expects this for this particular version of the file, it should override this
|
||||
/// method and return true.
|
||||
virtual bool versionHasSVOfileBreaks(PacketVersion thisVersion) const { return false; }
|
||||
|
||||
virtual void update() { } // nothing to do by default
|
||||
|
||||
OctreeElementPointer getRoot() { return _rootElement; }
|
||||
|
|
|
@ -491,6 +491,10 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationStep) {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (_entity->shouldSuppressLocationEdits()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isLocallyOwned()) {
|
||||
// we don't own the simulation
|
||||
|
||||
|
@ -577,7 +581,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_
|
|||
}
|
||||
|
||||
if (properties.transformChanged()) {
|
||||
if (_entity->checkAndMaybeUpdateQueryAACube()) {
|
||||
if (_entity->updateQueryAACube()) {
|
||||
// due to parenting, the server may not know where something is in world-space, so include the bounding cube.
|
||||
properties.setQueryAACube(_entity->getQueryAACube());
|
||||
}
|
||||
|
@ -644,7 +648,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_
|
|||
_entity->forEachDescendant([&](SpatiallyNestablePointer descendant) {
|
||||
if (descendant->getNestableType() == NestableType::Entity) {
|
||||
EntityItemPointer entityDescendant = std::static_pointer_cast<EntityItem>(descendant);
|
||||
if (descendant->checkAndMaybeUpdateQueryAACube()) {
|
||||
if (descendant->updateQueryAACube()) {
|
||||
EntityItemProperties newQueryCubeProperties;
|
||||
newQueryCubeProperties.setQueryAACube(descendant->getQueryAACube());
|
||||
newQueryCubeProperties.setLastEdited(properties.getLastEdited());
|
||||
|
|
|
@ -35,8 +35,8 @@ void DisplayPlugin::waitForPresent() {
|
|||
}
|
||||
}
|
||||
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&)> DisplayPlugin::getHUDOperator() {
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&)> hudOperator;
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> DisplayPlugin::getHUDOperator() {
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> hudOperator;
|
||||
{
|
||||
QMutexLocker locker(&_presentMutex);
|
||||
hudOperator = _hudOperator;
|
||||
|
|
|
@ -204,7 +204,7 @@ public:
|
|||
|
||||
void waitForPresent();
|
||||
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&)> getHUDOperator();
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> getHUDOperator();
|
||||
|
||||
static const QString& MENU_PATH();
|
||||
|
||||
|
@ -218,7 +218,7 @@ protected:
|
|||
|
||||
gpu::ContextPointer _gpuContext;
|
||||
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&)> _hudOperator { std::function<void(gpu::Batch&, const gpu::TexturePointer&)>() };
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> _hudOperator { std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)>() };
|
||||
|
||||
private:
|
||||
QMutex _presentMutex;
|
||||
|
|
|
@ -435,7 +435,7 @@ void DebugDeferredBuffer::run(const RenderContextPointer& renderContext, const I
|
|||
auto lightStage = renderContext->_scene->getStage<LightStage>();
|
||||
assert(lightStage);
|
||||
assert(lightStage->getNumLights() > 0);
|
||||
auto lightAndShadow = lightStage->getLightAndShadow(0);
|
||||
auto lightAndShadow = lightStage->getCurrentKeyLightAndShadow();
|
||||
const auto& globalShadow = lightAndShadow.second;
|
||||
if (globalShadow) {
|
||||
batch.setResourceTexture(Shadow, globalShadow->map);
|
||||
|
|
|
@ -498,7 +498,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
|
|||
auto lightStage = renderContext->_scene->getStage<LightStage>();
|
||||
assert(lightStage);
|
||||
assert(lightStage->getNumLights() > 0);
|
||||
auto lightAndShadow = lightStage->getLightAndShadow(0);
|
||||
auto lightAndShadow = lightStage->getCurrentKeyLightAndShadow();
|
||||
const auto& globalShadow = lightAndShadow.second;
|
||||
|
||||
// Bind the shadow buffer
|
||||
|
@ -509,7 +509,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
|
|||
auto& program = deferredLightingEffect->_directionalSkyboxLight;
|
||||
LightLocationsPtr locations = deferredLightingEffect->_directionalSkyboxLightLocations;
|
||||
|
||||
auto keyLight = lightStage->getLight(0);
|
||||
auto keyLight = lightAndShadow.first;
|
||||
|
||||
// Setup the global directional pass pipeline
|
||||
{
|
||||
|
|
|
@ -138,7 +138,8 @@ void main(void) {
|
|||
}
|
||||
|
||||
// Mix with background at far range
|
||||
if (distance > 32000.0) {
|
||||
const float BLEND_DISTANCE = 30000.0;
|
||||
if (distance > BLEND_DISTANCE) {
|
||||
outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlendValue);
|
||||
} else {
|
||||
outFragColor = potentialFragColor;
|
||||
|
|
|
@ -142,6 +142,11 @@ LightStage::LightPointer LightStage::removeLight(Index index) {
|
|||
LightPointer removed = _lights.freeElement(index);
|
||||
|
||||
if (removed) {
|
||||
auto shadowId = _descs[index].shadowId;
|
||||
// Remove shadow if one exists for this light
|
||||
if (shadowId != INVALID_INDEX) {
|
||||
_shadows.freeElement(shadowId);
|
||||
}
|
||||
_lightMap.erase(removed);
|
||||
_descs[index] = Desc();
|
||||
}
|
||||
|
|
|
@ -116,6 +116,30 @@ public:
|
|||
return LightAndShadow(getLight(lightId), getShadow(lightId));
|
||||
}
|
||||
|
||||
LightPointer getCurrentKeyLight() const {
|
||||
Index keyLightId{ 0 };
|
||||
if (!_currentFrame._sunLights.empty()) {
|
||||
keyLightId = _currentFrame._sunLights.front();
|
||||
}
|
||||
return _lights.get(keyLightId);
|
||||
}
|
||||
|
||||
ShadowPointer getCurrentKeyShadow() const {
|
||||
Index keyLightId{ 0 };
|
||||
if (!_currentFrame._sunLights.empty()) {
|
||||
keyLightId = _currentFrame._sunLights.front();
|
||||
}
|
||||
return getShadow(keyLightId);
|
||||
}
|
||||
|
||||
LightAndShadow getCurrentKeyLightAndShadow() const {
|
||||
Index keyLightId{ 0 };
|
||||
if (!_currentFrame._sunLights.empty()) {
|
||||
keyLightId = _currentFrame._sunLights.front();
|
||||
}
|
||||
return LightAndShadow(getLight(keyLightId), getShadow(keyLightId));
|
||||
}
|
||||
|
||||
LightStage();
|
||||
Lights _lights;
|
||||
LightMap _lightMap;
|
||||
|
|
|
@ -235,7 +235,6 @@ void Model::updateRenderItems() {
|
|||
self->updateClusterMatrices();
|
||||
|
||||
Transform modelTransform = self->getTransform();
|
||||
Transform physicsTransform = modelTransform;
|
||||
modelTransform.setScale(glm::vec3(1.0f));
|
||||
|
||||
uint32_t deleteGeometryCounter = self->_deleteGeometryCounter;
|
||||
|
@ -259,13 +258,12 @@ void Model::updateRenderItems() {
|
|||
});
|
||||
}
|
||||
|
||||
// collision mesh does not share the same unit scale as the FBX file's mesh: only apply offset
|
||||
Transform collisionMeshOffset;
|
||||
collisionMeshOffset.setIdentity();
|
||||
foreach(auto itemID, self->_collisionRenderItemsMap.keys()) {
|
||||
transaction.updateItem<MeshPartPayload>(itemID, [physicsTransform, collisionMeshOffset](MeshPartPayload& data) {
|
||||
transaction.updateItem<MeshPartPayload>(itemID, [modelTransform, collisionMeshOffset](MeshPartPayload& data) {
|
||||
// update the model transform for this render item.
|
||||
data.updateTransform(physicsTransform, collisionMeshOffset);
|
||||
data.updateTransform(modelTransform, collisionMeshOffset);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -441,7 +441,7 @@ void CompositeHUD::run(const RenderContextPointer& renderContext) {
|
|||
// Grab the HUD texture
|
||||
gpu::doInBatch(renderContext->args->_context, [&](gpu::Batch& batch) {
|
||||
if (renderContext->args->_hudOperator) {
|
||||
renderContext->args->_hudOperator(batch, renderContext->args->_hudTexture);
|
||||
renderContext->args->_hudOperator(batch, renderContext->args->_hudTexture, renderContext->args->_renderMode == RenderArgs::RenderMode::MIRROR_RENDER_MODE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -33,10 +33,8 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext,
|
|||
|
||||
auto lightStage = renderContext->_scene->getStage<LightStage>();
|
||||
assert(lightStage);
|
||||
LightStage::Index globalLightIndex { 0 };
|
||||
|
||||
const auto globalLight = lightStage->getLight(globalLightIndex);
|
||||
const auto shadow = lightStage->getShadow(globalLightIndex);
|
||||
const auto shadow = lightStage->getCurrentKeyShadow();
|
||||
if (!shadow) return;
|
||||
|
||||
const auto& fbo = shadow->framebuffer;
|
||||
|
@ -128,20 +126,22 @@ void RenderShadowTask::configure(const Config& configuration) {
|
|||
void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, Output& output) {
|
||||
auto lightStage = renderContext->_scene->getStage<LightStage>();
|
||||
assert(lightStage);
|
||||
const auto globalShadow = lightStage->getShadow(0);
|
||||
|
||||
// Cache old render args
|
||||
RenderArgs* args = renderContext->args;
|
||||
output = args->_renderMode;
|
||||
const auto globalShadow = lightStage->getCurrentKeyShadow();
|
||||
if (globalShadow) {
|
||||
// Cache old render args
|
||||
RenderArgs* args = renderContext->args;
|
||||
output = args->_renderMode;
|
||||
|
||||
auto nearClip = args->getViewFrustum().getNearClip();
|
||||
float nearDepth = -args->_boomOffset.z;
|
||||
const int SHADOW_FAR_DEPTH = 20;
|
||||
globalShadow->setKeylightFrustum(args->getViewFrustum(), nearDepth, nearClip + SHADOW_FAR_DEPTH);
|
||||
auto nearClip = args->getViewFrustum().getNearClip();
|
||||
float nearDepth = -args->_boomOffset.z;
|
||||
const int SHADOW_FAR_DEPTH = 20;
|
||||
globalShadow->setKeylightFrustum(args->getViewFrustum(), nearDepth, nearClip + SHADOW_FAR_DEPTH);
|
||||
|
||||
// Set the keylight render args
|
||||
args->pushViewFrustum(*(globalShadow->getFrustum()));
|
||||
args->_renderMode = RenderArgs::SHADOW_RENDER_MODE;
|
||||
// Set the keylight render args
|
||||
args->pushViewFrustum(*(globalShadow->getFrustum()));
|
||||
args->_renderMode = RenderArgs::SHADOW_RENDER_MODE;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderShadowTeardown::run(const render::RenderContextPointer& renderContext, const Input& input) {
|
||||
|
|
|
@ -122,7 +122,7 @@ namespace render {
|
|||
render::ScenePointer _scene;
|
||||
int8_t _cameraMode { -1 };
|
||||
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&)> _hudOperator;
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> _hudOperator;
|
||||
gpu::TexturePointer _hudTexture;
|
||||
};
|
||||
|
||||
|
|
|
@ -46,6 +46,8 @@ void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QString
|
|||
}
|
||||
break;
|
||||
case SHAPE_TYPE_COMPOUND:
|
||||
case SHAPE_TYPE_SIMPLE_HULL:
|
||||
case SHAPE_TYPE_SIMPLE_COMPOUND:
|
||||
case SHAPE_TYPE_STATIC_MESH:
|
||||
_url = QUrl(url);
|
||||
break;
|
||||
|
@ -250,16 +252,26 @@ const DoubleHashKey& ShapeInfo::getHash() const {
|
|||
}
|
||||
_doubleHashKey.setHash2(hash);
|
||||
|
||||
if (_type == SHAPE_TYPE_COMPOUND || _type == SHAPE_TYPE_STATIC_MESH) {
|
||||
QString url = _url.toString();
|
||||
if (!url.isEmpty()) {
|
||||
// fold the urlHash into both parts
|
||||
QByteArray baUrl = url.toLocal8Bit();
|
||||
const char *cUrl = baUrl.data();
|
||||
uint32_t urlHash = qChecksum(cUrl, baUrl.count());
|
||||
_doubleHashKey.setHash(_doubleHashKey.getHash() ^ urlHash);
|
||||
_doubleHashKey.setHash2(_doubleHashKey.getHash2() ^ urlHash);
|
||||
}
|
||||
QString url = _url.toString();
|
||||
if (!url.isEmpty()) {
|
||||
// fold the urlHash into both parts
|
||||
QByteArray baUrl = url.toLocal8Bit();
|
||||
uint32_t urlHash = qChecksum(baUrl.data(), baUrl.size());
|
||||
_doubleHashKey.setHash(_doubleHashKey.getHash() ^ urlHash);
|
||||
_doubleHashKey.setHash2(_doubleHashKey.getHash2() ^ urlHash);
|
||||
}
|
||||
|
||||
uint32_t numHulls = 0;
|
||||
if (_type == SHAPE_TYPE_COMPOUND || _type == SHAPE_TYPE_SIMPLE_COMPOUND) {
|
||||
numHulls = (uint32_t)_pointCollection.size();
|
||||
} else if (_type == SHAPE_TYPE_SIMPLE_HULL) {
|
||||
numHulls = 1;
|
||||
}
|
||||
if (numHulls > 0) {
|
||||
hash = DoubleHashKey::hashFunction(numHulls, primeIndex++);
|
||||
_doubleHashKey.setHash(_doubleHashKey.getHash() ^ hash);
|
||||
hash = DoubleHashKey::hashFunction2(numHulls);
|
||||
_doubleHashKey.setHash2(_doubleHashKey.getHash2() ^ hash);
|
||||
}
|
||||
}
|
||||
return _doubleHashKey;
|
||||
|
|
|
@ -963,35 +963,41 @@ AACube SpatiallyNestable::getMaximumAACube(bool& success) const {
|
|||
|
||||
const float PARENTED_EXPANSION_FACTOR = 3.0f;
|
||||
|
||||
bool SpatiallyNestable::checkAndMaybeUpdateQueryAACube() {
|
||||
bool success = false;
|
||||
AACube maxAACube = getMaximumAACube(success);
|
||||
if (success) {
|
||||
// maybe update _queryAACube
|
||||
if (!_queryAACubeSet || (_parentID.isNull() && _children.size() == 0) || !_queryAACube.contains(maxAACube)) {
|
||||
if (_parentJointIndex != INVALID_JOINT_INDEX || _children.size() > 0 ) {
|
||||
// make an expanded AACube centered on the object
|
||||
float scale = PARENTED_EXPANSION_FACTOR * maxAACube.getScale();
|
||||
_queryAACube = AACube(maxAACube.calcCenter() - glm::vec3(0.5f * scale), scale);
|
||||
} else {
|
||||
_queryAACube = maxAACube;
|
||||
}
|
||||
|
||||
forEachDescendant([&](const SpatiallyNestablePointer& descendant) {
|
||||
bool childSuccess;
|
||||
AACube descendantAACube = descendant->getQueryAACube(childSuccess);
|
||||
if (childSuccess) {
|
||||
if (_queryAACube.contains(descendantAACube)) {
|
||||
return ;
|
||||
}
|
||||
_queryAACube += descendantAACube.getMinimumPoint();
|
||||
_queryAACube += descendantAACube.getMaximumPoint();
|
||||
}
|
||||
});
|
||||
_queryAACubeSet = true;
|
||||
}
|
||||
bool SpatiallyNestable::updateQueryAACube() {
|
||||
if (!queryAACubeNeedsUpdate()) {
|
||||
return false;
|
||||
}
|
||||
return success;
|
||||
|
||||
bool success;
|
||||
AACube maxAACube = getMaximumAACube(success);
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (shouldPuffQueryAACube()) {
|
||||
// make an expanded AACube centered on the object
|
||||
float scale = PARENTED_EXPANSION_FACTOR * maxAACube.getScale();
|
||||
_queryAACube = AACube(maxAACube.calcCenter() - glm::vec3(0.5f * scale), scale);
|
||||
_queryAACubeIsPuffed = true;
|
||||
} else {
|
||||
_queryAACube = maxAACube;
|
||||
_queryAACubeIsPuffed = false;
|
||||
}
|
||||
|
||||
forEachDescendant([&](const SpatiallyNestablePointer& descendant) {
|
||||
bool childSuccess;
|
||||
AACube descendantAACube = descendant->getQueryAACube(childSuccess);
|
||||
if (childSuccess) {
|
||||
if (_queryAACube.contains(descendantAACube)) {
|
||||
return; // from lambda
|
||||
}
|
||||
_queryAACube += descendantAACube.getMinimumPoint();
|
||||
_queryAACube += descendantAACube.getMaximumPoint();
|
||||
}
|
||||
});
|
||||
|
||||
_queryAACubeSet = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void SpatiallyNestable::setQueryAACube(const AACube& queryAACube) {
|
||||
|
@ -1008,6 +1014,16 @@ bool SpatiallyNestable::queryAACubeNeedsUpdate() const {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool success;
|
||||
AACube maxAACube = getMaximumAACube(success);
|
||||
if (success && !_queryAACube.contains(maxAACube)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (shouldPuffQueryAACube() != _queryAACubeIsPuffed) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// make sure children are still in their boxes, also.
|
||||
bool childNeedsUpdate = false;
|
||||
forEachDescendantTest([&](const SpatiallyNestablePointer& descendant) {
|
||||
|
@ -1021,31 +1037,6 @@ bool SpatiallyNestable::queryAACubeNeedsUpdate() const {
|
|||
return childNeedsUpdate;
|
||||
}
|
||||
|
||||
void SpatiallyNestable::updateQueryAACube() {
|
||||
bool success;
|
||||
AACube maxAACube = getMaximumAACube(success);
|
||||
if (_parentJointIndex != INVALID_JOINT_INDEX || _children.size() > 0 ) {
|
||||
// make an expanded AACube centered on the object
|
||||
float scale = PARENTED_EXPANSION_FACTOR * maxAACube.getScale();
|
||||
_queryAACube = AACube(maxAACube.calcCenter() - glm::vec3(0.5f * scale), scale);
|
||||
} else {
|
||||
_queryAACube = maxAACube;
|
||||
}
|
||||
|
||||
forEachDescendant([&](const SpatiallyNestablePointer& descendant) {
|
||||
bool success;
|
||||
AACube descendantAACube = descendant->getQueryAACube(success);
|
||||
if (success) {
|
||||
if (_queryAACube.contains(descendantAACube)) {
|
||||
return;
|
||||
}
|
||||
_queryAACube += descendantAACube.getMinimumPoint();
|
||||
_queryAACube += descendantAACube.getMaximumPoint();
|
||||
}
|
||||
});
|
||||
_queryAACubeSet = true;
|
||||
}
|
||||
|
||||
AACube SpatiallyNestable::getQueryAACube(bool& success) const {
|
||||
if (_queryAACubeSet) {
|
||||
success = true;
|
||||
|
|
|
@ -106,11 +106,11 @@ public:
|
|||
virtual glm::vec3 getParentAngularVelocity(bool& success) const;
|
||||
|
||||
virtual AACube getMaximumAACube(bool& success) const;
|
||||
bool checkAndMaybeUpdateQueryAACube();
|
||||
void updateQueryAACube();
|
||||
|
||||
virtual void setQueryAACube(const AACube& queryAACube);
|
||||
virtual bool queryAACubeNeedsUpdate() const;
|
||||
virtual bool shouldPuffQueryAACube() const { return false; }
|
||||
bool updateQueryAACube();
|
||||
void forceQueryAACubeUpdate() { _queryAACubeSet = false; }
|
||||
virtual AACube getQueryAACube(bool& success) const;
|
||||
virtual AACube getQueryAACube() const;
|
||||
|
@ -234,6 +234,7 @@ private:
|
|||
glm::vec3 _angularVelocity;
|
||||
mutable bool _parentKnowsMe { false };
|
||||
bool _isDead { false };
|
||||
bool _queryAACubeIsPuffed { false };
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -104,8 +104,9 @@ bool TriangleSet::TriangleOctreeCell::findRayIntersectionInternal(const glm::vec
|
|||
if (_bounds.findRayIntersection(origin, direction, boxDistance, face, surfaceNormal)) {
|
||||
|
||||
// if our bounding box intersects at a distance greater than the current known
|
||||
// best distance, than we can safely not check any of our triangles
|
||||
if (boxDistance > bestDistance) {
|
||||
// best distance, and our origin isn't inside the boounds, then we can safely
|
||||
// not check any of our triangles
|
||||
if (boxDistance > bestDistance && !_bounds.contains(origin)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1082,37 +1082,7 @@ void OffscreenQmlSurface::synthesizeKeyPress(QString key, QObject* targetOverrid
|
|||
}
|
||||
}
|
||||
|
||||
static void forEachKeyboard(QQuickItem* parent, std::function<void(QQuickItem*)> function) {
|
||||
if (!function) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto keyboards = parent->findChildren<QObject*>("keyboard");
|
||||
|
||||
for (auto keyboardObject : keyboards) {
|
||||
auto keyboard = qobject_cast<QQuickItem*>(keyboardObject);
|
||||
if (keyboard) {
|
||||
function(keyboard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const int TEXTINPUT_PASSWORD = 2;
|
||||
|
||||
static QQuickItem* getTopmostParent(QQuickItem* item) {
|
||||
QObject* itemObject = item;
|
||||
while (itemObject) {
|
||||
if (itemObject->parent()) {
|
||||
itemObject = itemObject->parent();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return qobject_cast<QQuickItem*> (itemObject);
|
||||
}
|
||||
|
||||
void OffscreenQmlSurface::setKeyboardRaised(QObject* object, bool raised, bool numeric) {
|
||||
void OffscreenQmlSurface::setKeyboardRaised(QObject* object, bool raised, bool numeric, bool passwordField) {
|
||||
#if Q_OS_ANDROID
|
||||
return;
|
||||
#endif
|
||||
|
@ -1128,21 +1098,6 @@ void OffscreenQmlSurface::setKeyboardRaised(QObject* object, bool raised, bool n
|
|||
return;
|
||||
}
|
||||
|
||||
auto echoMode = item->property("echoMode");
|
||||
bool isPasswordField = echoMode.isValid() && echoMode.toInt() == TEXTINPUT_PASSWORD;
|
||||
|
||||
// we need to somehow pass 'isPasswordField' to visible keyboard so it will change its 'mirror text' to asterixes
|
||||
// the issue in some cases there might be more than one keyboard in object tree and it is hard to understand which one is being used at the moment
|
||||
// unfortunately attempts to check for visibility failed becuase visibility is not updated yet. So... I don't see other way than just update properties for all the keyboards
|
||||
|
||||
auto topmostParent = getTopmostParent(item);
|
||||
if (topmostParent) {
|
||||
forEachKeyboard(topmostParent, [&](QQuickItem* keyboard) {
|
||||
keyboard->setProperty("mirroredText", QVariant::fromValue(QString("")));
|
||||
keyboard->setProperty("password", isPasswordField);
|
||||
});
|
||||
}
|
||||
|
||||
// for future probably makes sense to consider one of the following:
|
||||
// 1. make keyboard a singleton, which will be dynamically re-parented before showing
|
||||
// 2. track currently visible keyboard somewhere, allow to subscribe for this signal
|
||||
|
@ -1153,15 +1108,15 @@ void OffscreenQmlSurface::setKeyboardRaised(QObject* object, bool raised, bool n
|
|||
numeric = numeric || QString(item->metaObject()->className()).left(7) == "SpinBox";
|
||||
|
||||
if (item->property("keyboardRaised").isValid()) {
|
||||
forEachKeyboard(item, [&](QQuickItem* keyboard) {
|
||||
keyboard->setProperty("mirroredText", QVariant::fromValue(QString("")));
|
||||
keyboard->setProperty("password", isPasswordField);
|
||||
});
|
||||
|
||||
// FIXME - HMD only: Possibly set value of "keyboardEnabled" per isHMDMode() for use in WebView.qml.
|
||||
if (item->property("punctuationMode").isValid()) {
|
||||
item->setProperty("punctuationMode", QVariant(numeric));
|
||||
}
|
||||
if (item->property("passwordField").isValid()) {
|
||||
item->setProperty("passwordField", QVariant(passwordField));
|
||||
}
|
||||
|
||||
item->setProperty("keyboardRaised", QVariant(raised));
|
||||
return;
|
||||
}
|
||||
|
@ -1186,9 +1141,13 @@ void OffscreenQmlSurface::emitWebEvent(const QVariant& message) {
|
|||
const QString RAISE_KEYBOARD = "_RAISE_KEYBOARD";
|
||||
const QString RAISE_KEYBOARD_NUMERIC = "_RAISE_KEYBOARD_NUMERIC";
|
||||
const QString LOWER_KEYBOARD = "_LOWER_KEYBOARD";
|
||||
const QString RAISE_KEYBOARD_NUMERIC_PASSWORD = "_RAISE_KEYBOARD_NUMERIC_PASSWORD";
|
||||
const QString RAISE_KEYBOARD_PASSWORD = "_RAISE_KEYBOARD_PASSWORD";
|
||||
QString messageString = message.type() == QVariant::String ? message.toString() : "";
|
||||
if (messageString.left(RAISE_KEYBOARD.length()) == RAISE_KEYBOARD) {
|
||||
setKeyboardRaised(_currentFocusItem, true, messageString == RAISE_KEYBOARD_NUMERIC);
|
||||
bool numeric = (messageString == RAISE_KEYBOARD_NUMERIC || messageString == RAISE_KEYBOARD_NUMERIC_PASSWORD);
|
||||
bool passwordField = (messageString == RAISE_KEYBOARD_PASSWORD || messageString == RAISE_KEYBOARD_NUMERIC_PASSWORD);
|
||||
setKeyboardRaised(_currentFocusItem, true, numeric, passwordField);
|
||||
} else if (messageString == LOWER_KEYBOARD) {
|
||||
setKeyboardRaised(_currentFocusItem, false);
|
||||
} else {
|
||||
|
|
|
@ -82,7 +82,7 @@ public:
|
|||
QPointF mapToVirtualScreen(const QPointF& originalPoint, QObject* originalWidget);
|
||||
bool eventFilter(QObject* originalDestination, QEvent* event) override;
|
||||
|
||||
void setKeyboardRaised(QObject* object, bool raised, bool numeric = false);
|
||||
void setKeyboardRaised(QObject* object, bool raised, bool numeric = false, bool passwordField = false);
|
||||
Q_INVOKABLE void synthesizeKeyPress(QString key, QObject* targetOverride = nullptr);
|
||||
|
||||
using TextureAndFence = std::pair<uint32_t, void*>;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// examples
|
||||
//
|
||||
// Created by Brad hefta-Gaub on 10/1/14.
|
||||
// Modified by Daniela Fontes @DanielaFifo and Tiago Andrade @TagoWill on 4/7/2017
|
||||
// Modified by Daniela Fontes * @DanielaFifo and Tiago Andrade @TagoWill on 4/7/2017
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// This script implements a class useful for building tools for editing entities.
|
||||
|
@ -203,6 +203,7 @@ SelectionManager = (function() {
|
|||
print("ERROR: entitySelectionTool.update got exception: " + JSON.stringify(e));
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
return that;
|
||||
|
@ -1422,11 +1423,11 @@ SelectionDisplay = (function() {
|
|||
Overlays.editOverlay(rollHandle, {
|
||||
scale: handleSize
|
||||
});
|
||||
var pos = Vec3.sum(grabberMoveUpPosition, {
|
||||
x: 0,
|
||||
y: Vec3.length(diff) * GRABBER_DISTANCE_TO_SIZE_RATIO * 3,
|
||||
z: 0
|
||||
});
|
||||
var upDiff = Vec3.multiply((
|
||||
Vec3.length(diff) * GRABBER_DISTANCE_TO_SIZE_RATIO * 3),
|
||||
Quat.getUp(MyAvatar.orientation)
|
||||
);
|
||||
var pos = Vec3.sum(grabberMoveUpPosition, upDiff);
|
||||
Overlays.editOverlay(grabberMoveUp, {
|
||||
position: pos,
|
||||
scale: handleSize / 1.25
|
||||
|
@ -2099,10 +2100,11 @@ SelectionDisplay = (function() {
|
|||
});
|
||||
|
||||
var grabberMoveUpOffset = 0.1;
|
||||
var upVec = Quat.getUp(MyAvatar.orientation);
|
||||
grabberMoveUpPosition = {
|
||||
x: position.x,
|
||||
y: position.y + worldTop + grabberMoveUpOffset,
|
||||
z: position.z
|
||||
x: position.x + (grabberMoveUpOffset + worldTop) * upVec.x ,
|
||||
y: position.y+ (grabberMoveUpOffset + worldTop) * upVec.y,
|
||||
z: position.z + (grabberMoveUpOffset + worldTop) * upVec.z
|
||||
};
|
||||
Overlays.editOverlay(grabberMoveUp, {
|
||||
visible: (!activeTool) || isActiveTool(grabberMoveUp)
|
||||
|
@ -2416,9 +2418,6 @@ SelectionDisplay = (function() {
|
|||
mode: "TRANSLATE_UP_DOWN",
|
||||
onBegin: function(event, pickRay, pickResult) {
|
||||
upDownPickNormal = Quat.getForward(lastCameraOrientation);
|
||||
// Remove y component so the y-axis lies along the plane we're picking on - this will
|
||||
// give movements that follow the mouse.
|
||||
upDownPickNormal.y = 0;
|
||||
lastXYPick = rayPlaneIntersection(pickRay, SelectionManager.worldPosition, upDownPickNormal);
|
||||
|
||||
SelectionManager.saveProperties();
|
||||
|
@ -2455,11 +2454,17 @@ SelectionDisplay = (function() {
|
|||
var newIntersection = rayPlaneIntersection(pickRay, SelectionManager.worldPosition, upDownPickNormal);
|
||||
|
||||
var vector = Vec3.subtract(newIntersection, lastXYPick);
|
||||
|
||||
// project vector onto avatar up vector
|
||||
// we want the avatar referential not the camera.
|
||||
var avatarUpVector = Quat.getUp(MyAvatar.orientation);
|
||||
var dotVectorUp = Vec3.dot(vector, avatarUpVector);
|
||||
vector = Vec3.multiply(dotVectorUp, avatarUpVector);
|
||||
|
||||
|
||||
vector = grid.snapToGrid(vector);
|
||||
|
||||
// we only care about the Y axis
|
||||
vector.x = 0;
|
||||
vector.z = 0;
|
||||
|
||||
|
||||
var wantDebug = false;
|
||||
if (wantDebug) {
|
||||
|
|
|
@ -74,8 +74,8 @@
|
|||
itemName: 'Test Flaregun',
|
||||
itemPrice: (debugError ? 10 : 17),
|
||||
itemHref: 'http://mpassets.highfidelity.com/0d90d21c-ce7a-4990-ad18-e9d2cf991027-v1/flaregun.json',
|
||||
},
|
||||
canRezCertifiedItems: Entities.canRezCertified || Entities.canRezTmpCertified
|
||||
categories: ["Wearables", "Miscellaneous"]
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -115,7 +115,6 @@
|
|||
if (url === MARKETPLACE_PURCHASES_QML_PATH) {
|
||||
tablet.sendToQml({
|
||||
method: 'updatePurchases',
|
||||
canRezCertifiedItems: Entities.canRezCertified || Entities.canRezTmpCertified,
|
||||
referrerURL: referrerURL,
|
||||
filterText: filterText
|
||||
});
|
||||
|
@ -136,9 +135,10 @@
|
|||
|
||||
function setCertificateInfo(currentEntityWithContextOverlay, itemCertificateId) {
|
||||
wireEventBridge(true);
|
||||
var certificateId = itemCertificateId || (Entities.getEntityProperties(currentEntityWithContextOverlay, ['certificateID']).certificateID + "\n");
|
||||
tablet.sendToQml({
|
||||
method: 'inspectionCertificate_setCertificateId',
|
||||
certificateId: itemCertificateId || Entities.getEntityProperties(currentEntityWithContextOverlay, ['certificateID']).certificateID
|
||||
certificateId: certificateId
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -203,8 +203,7 @@
|
|||
tablet.pushOntoStack(MARKETPLACE_CHECKOUT_QML_PATH);
|
||||
tablet.sendToQml({
|
||||
method: 'updateCheckoutQML',
|
||||
params: parsedJsonMessage,
|
||||
canRezCertifiedItems: Entities.canRezCertified || Entities.canRezTmpCertified
|
||||
params: parsedJsonMessage
|
||||
});
|
||||
} else if (parsedJsonMessage.type === "REQUEST_SETTING") {
|
||||
sendCommerceSettings();
|
||||
|
|
Loading…
Reference in a new issue