Merge branch 'master' of https://github.com/highfidelity/hifi into pop_dynamicTestsMaster

This commit is contained in:
Zach Fox 2017-10-25 10:26:50 -07:00
commit 91333cdf7b
79 changed files with 782 additions and 890 deletions

View file

@ -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) {

View file

@ -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);

View file

@ -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 = "<"

View file

@ -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 = "<"

View file

@ -39,6 +39,10 @@ Rectangle {
property bool shiftMode: false
property bool numericShiftMode: false
onRaisedChanged: {
mirroredText = "";
}
function resetShiftMode(mode) {
shiftMode = mode;
shiftKey.resetToggledMode(mode);

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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"
}
}

View file

@ -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;

View file

@ -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"
}
}
}

View file

@ -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);
}
}
}

View file

@ -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;

View file

@ -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});
}
}

View file

@ -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;

View file

@ -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;

View file

@ -5091,6 +5091,7 @@ void Application::update(float deltaTime) {
}
this->updateCamera(appRenderArgs._renderArgs);
appRenderArgs._eyeToWorld = _myCamera.getTransform();
appRenderArgs._isStereo = false;
{

View file

@ -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);

View file

@ -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;

View file

@ -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);
}

View file

@ -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) {

View file

@ -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) {

View file

@ -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;

View file

@ -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);
}

View file

@ -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;
};

View file

@ -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>();

View file

@ -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

View file

@ -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);

View file

@ -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);
bool showCollisionGeometry = (bool)(args->_debugFlags & (int)RenderArgs::RENDER_DEBUG_HULLS);
if (showCollisionGeometry != _showCollisionGeometry) {
_showCollisionGeometry = showCollisionGeometry;
flagForCollisionGeometryUpdate();
}
// clear model's collision geometry
model::MeshPointer mesh = nullptr;
_model->setCollisionMesh(mesh);
}
}
#endif
}
void ModelEntityRenderer::mapJoints(const TypedEntityPointer& entity, const QStringList& modelJointNames) {

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -32,6 +32,7 @@ private:
Procedural _procedural;
QString _lastUserData;
Transform _renderTransform;
entity::Shape _shape { entity::Sphere };
glm::vec4 _color;
glm::vec3 _position;

View file

@ -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));

View file

@ -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;

View file

@ -62,6 +62,7 @@ private:
uint16_t _lastDPI;
QTimer _timer;
uint64_t _lastRenderTime { 0 };
Transform _renderTransform;
};
} } // namespace

View file

@ -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);
}
}

View file

@ -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

View file

@ -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,7 +586,6 @@ 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);
@ -622,7 +613,6 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
qCDebug(entities) << " lastSimulatedFromBufferAdjusted:" << debugTime(lastSimulatedFromBufferAdjusted, now);
#endif
}
}
#ifdef WANT_DEBUG
if (overwriteLocalData) {
@ -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,10 +813,7 @@ 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);
@ -836,7 +823,6 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
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([&] {

View file

@ -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

View file

@ -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(&paramCount);
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__);

View file

@ -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);

View file

@ -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 {

View file

@ -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);

View file

@ -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]

View file

@ -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);
}
return bytesRead;
}

View file

@ -111,27 +111,9 @@ 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_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()
@ -142,7 +124,6 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
bytesRead += bytesFromAnimation;
dataAt += bytesFromAnimation;
}
READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, setShapeType);

View file

@ -464,52 +464,21 @@ 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_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);
}
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);
}
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);
@ -517,9 +486,7 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch
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);
@ -529,11 +496,8 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch
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);
}
return bytesRead;
}

View file

@ -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();

View 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));
}

View file

@ -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));

View file

@ -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;

View file

@ -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>();

View file

@ -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

View file

@ -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:

View file

@ -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,

View file

@ -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) {

View file

@ -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; }

View file

@ -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());

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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
{

View file

@ -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;

View file

@ -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();
}

View file

@ -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;

View file

@ -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);
});
}

View file

@ -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);
}
});
}

View file

@ -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,8 +126,9 @@ 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);
const auto globalShadow = lightStage->getCurrentKeyShadow();
if (globalShadow) {
// Cache old render args
RenderArgs* args = renderContext->args;
output = args->_renderMode;
@ -142,6 +141,7 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, O
// 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) {

View file

@ -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;
};

View file

@ -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());
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;

View file

@ -963,18 +963,25 @@ AACube SpatiallyNestable::getMaximumAACube(bool& success) const {
const float PARENTED_EXPANSION_FACTOR = 3.0f;
bool SpatiallyNestable::checkAndMaybeUpdateQueryAACube() {
bool success = false;
bool SpatiallyNestable::updateQueryAACube() {
if (!queryAACubeNeedsUpdate()) {
return false;
}
bool success;
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 ) {
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) {
@ -982,16 +989,15 @@ bool SpatiallyNestable::checkAndMaybeUpdateQueryAACube() {
AACube descendantAACube = descendant->getQueryAACube(childSuccess);
if (childSuccess) {
if (_queryAACube.contains(descendantAACube)) {
return ;
return; // from lambda
}
_queryAACube += descendantAACube.getMinimumPoint();
_queryAACube += descendantAACube.getMaximumPoint();
}
});
_queryAACubeSet = true;
}
}
return success;
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;

View file

@ -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 };
};

View file

@ -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;
}

View file

@ -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 {

View file

@ -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*>;

View file

@ -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) {

View file

@ -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();