mirror of
https://github.com/overte-org/overte.git
synced 2025-08-17 00:56:16 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into blue
This commit is contained in:
commit
50a3ccdbca
104 changed files with 1309 additions and 719 deletions
2
BUILD.md
2
BUILD.md
|
@ -25,7 +25,7 @@ The above dependencies will be downloaded, built, linked and included automatica
|
|||
|
||||
These are not placed in your normal build tree when doing an out of source build so that they do not need to be re-downloaded and re-compiled every time the CMake build folder is cleared. Should you want to force a re-download and re-compile of a specific external, you can simply remove that directory from the appropriate subfolder in `build/ext`. Should you want to force a re-download and re-compile of all externals, just remove the `build/ext` folder.
|
||||
|
||||
If you would like to use a specific install of a dependency instead of the version that would be grabbed as a CMake ExternalProject, you can pass -DUSE_LOCAL_$NAME=0 (where $NAME is the name of the subfolder in [cmake/externals](cmake/externals)) when you run CMake to tell it not to get that dependency as an external project.
|
||||
If you would like to use a specific install of a dependency instead of the version that would be grabbed as a CMake ExternalProject, you can pass -DUSE\_LOCAL\_$NAME=0 (where $NAME is the name of the subfolder in [cmake/externals](cmake/externals)) when you run CMake to tell it not to get that dependency as an external project.
|
||||
|
||||
### OS Specific Build Guides
|
||||
|
||||
|
|
|
@ -210,6 +210,7 @@ endif()
|
|||
# link required hifi libraries
|
||||
link_hifi_libraries(
|
||||
shared octree ktx gpu gl gpu-gl procedural model render
|
||||
pointers
|
||||
recording fbx networking model-networking entities avatars trackers
|
||||
audio audio-client animation script-engine physics
|
||||
render-utils entities-renderer avatars-renderer ui auto-updater midi
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4 as Original
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import TabletScriptingInterface 1.0
|
||||
|
||||
import "../styles-uit"
|
||||
|
||||
|
@ -26,6 +27,16 @@ Original.Button {
|
|||
|
||||
HifiConstants { id: hifi }
|
||||
|
||||
onHoveredChanged: {
|
||||
if (hovered) {
|
||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
||||
}
|
||||
|
||||
style: ButtonStyle {
|
||||
|
||||
background: Rectangle {
|
||||
|
|
|
@ -14,6 +14,8 @@ import QtQuick.Controls.Styles 1.4
|
|||
|
||||
import "../styles-uit"
|
||||
|
||||
import TabletScriptingInterface 1.0
|
||||
|
||||
Original.CheckBox {
|
||||
id: checkBox
|
||||
|
||||
|
@ -28,6 +30,15 @@ Original.CheckBox {
|
|||
readonly property int checkRadius: 2
|
||||
activeFocusOnPress: true
|
||||
|
||||
onClicked: {
|
||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
||||
}
|
||||
|
||||
// TODO: doesnt works for QQC1. check with QQC2
|
||||
// onHovered: {
|
||||
// tabletInterface.playSound(TabletEnums.ButtonHover);
|
||||
// }
|
||||
|
||||
style: CheckBoxStyle {
|
||||
indicator: Rectangle {
|
||||
id: box
|
||||
|
|
|
@ -13,6 +13,7 @@ import QtQuick.Controls 2.2
|
|||
|
||||
import "../styles-uit"
|
||||
import "../controls-uit" as HiFiControls
|
||||
import TabletScriptingInterface 1.0
|
||||
|
||||
CheckBox {
|
||||
id: checkBox
|
||||
|
@ -32,6 +33,17 @@ CheckBox {
|
|||
readonly property int checkSize: Math.max(boxSize - 8, 10)
|
||||
readonly property int checkRadius: isRound ? checkSize / 2 : 2
|
||||
focusPolicy: Qt.ClickFocus
|
||||
hoverEnabled: true
|
||||
|
||||
onClicked: {
|
||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
||||
}
|
||||
|
||||
onHoveredChanged: {
|
||||
if (hovered) {
|
||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
||||
}
|
||||
}
|
||||
|
||||
indicator: Rectangle {
|
||||
id: box
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4 as Original
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import TabletScriptingInterface 1.0
|
||||
|
||||
import "../styles-uit"
|
||||
|
||||
|
@ -24,6 +25,16 @@ Original.Button {
|
|||
width: 120
|
||||
height: 28
|
||||
|
||||
onHoveredChanged: {
|
||||
if (hovered) {
|
||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
||||
}
|
||||
|
||||
style: ButtonStyle {
|
||||
|
||||
background: Rectangle {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import QtQuick 2.0
|
||||
import TabletScriptingInterface 1.0
|
||||
|
||||
Item {
|
||||
id: keyItem
|
||||
|
@ -32,8 +33,15 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
onContainsMouseChanged: {
|
||||
if (containsMouse) {
|
||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
mouse.accepted = true;
|
||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
||||
|
||||
webEntity.synthesizeKeyPress(glyph);
|
||||
webEntity.synthesizeKeyPress(glyph, mirrorText);
|
||||
|
|
|
@ -15,6 +15,8 @@ import QtQuick.Controls.Styles 1.4
|
|||
import "../styles-uit"
|
||||
import "../controls-uit" as HifiControls
|
||||
|
||||
import TabletScriptingInterface 1.0
|
||||
|
||||
Original.RadioButton {
|
||||
id: radioButton
|
||||
HifiConstants { id: hifi }
|
||||
|
@ -27,6 +29,15 @@ Original.RadioButton {
|
|||
readonly property int checkSize: 10
|
||||
readonly property int checkRadius: 2
|
||||
|
||||
onClicked: {
|
||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
||||
}
|
||||
|
||||
// TODO: doesnt works for QQC1. check with QQC2
|
||||
// onHovered: {
|
||||
// tabletInterface.playSound(TabletEnums.ButtonHover);
|
||||
// }
|
||||
|
||||
style: RadioButtonStyle {
|
||||
indicator: Rectangle {
|
||||
id: box
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import TabletScriptingInterface 1.0
|
||||
|
||||
import "../../controls-uit"
|
||||
|
||||
|
@ -22,7 +23,16 @@ Preference {
|
|||
|
||||
Button {
|
||||
id: button
|
||||
onClicked: preference.trigger()
|
||||
onHoveredChanged: {
|
||||
if (hovered) {
|
||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
preference.trigger();
|
||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
||||
}
|
||||
width: 180
|
||||
anchors.bottom: parent.bottom
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import TabletScriptingInterface 1.0
|
||||
|
||||
import "../../controls-uit"
|
||||
|
||||
|
@ -38,6 +39,16 @@ Preference {
|
|||
|
||||
CheckBox {
|
||||
id: checkBox
|
||||
onHoveredChanged: {
|
||||
if (hovered) {
|
||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
||||
}
|
||||
|
||||
anchors {
|
||||
top: spacer.bottom
|
||||
left: parent.left
|
||||
|
|
|
@ -14,6 +14,8 @@ import QtQuick.Controls 1.4
|
|||
import QtQuick.Layouts 1.3
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
import TabletScriptingInterface 1.0
|
||||
|
||||
Rectangle {
|
||||
readonly property var level: Audio.inputLevel;
|
||||
|
||||
|
@ -57,8 +59,16 @@ Rectangle {
|
|||
|
||||
hoverEnabled: true;
|
||||
scrollGestureEnabled: false;
|
||||
onClicked: { Audio.muted = !Audio.muted; }
|
||||
onClicked: {
|
||||
Audio.muted = !Audio.muted;
|
||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
||||
}
|
||||
drag.target: dragTarget;
|
||||
onContainsMouseChanged: {
|
||||
if (containsMouse) {
|
||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QtObject {
|
||||
|
|
|
@ -239,6 +239,25 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HifiCommerceCommon.FirstUseTutorial {
|
||||
id: firstUseTutorial;
|
||||
z: 999;
|
||||
visible: root.activeView === "firstUseTutorial";
|
||||
anchors.fill: parent;
|
||||
|
||||
Connections {
|
||||
onSendSignalToParent: {
|
||||
switch (message.method) {
|
||||
case 'tutorial_skipClicked':
|
||||
case 'tutorial_finished':
|
||||
Settings.setValue("isFirstUseOfPurchases", false);
|
||||
root.activeView = "checkoutSuccess";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -611,6 +630,28 @@ Rectangle {
|
|||
lightboxPopup.visible = true;
|
||||
}
|
||||
}
|
||||
RalewaySemiBold {
|
||||
id: explainRezText;
|
||||
//visible: !root.isWearable;
|
||||
text: '<font color="' + hifi.colors.redAccent + '"><a href="#">What does "Rez" mean?</a></font>'
|
||||
// Text size
|
||||
size: 16;
|
||||
// Anchors
|
||||
anchors.top: noPermissionText.visible ? noPermissionText.bottom : rezNowButton.bottom;
|
||||
anchors.topMargin: 6;
|
||||
height: paintedHeight;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
// Style
|
||||
color: hifi.colors.redAccent;
|
||||
wrapMode: Text.WordWrap;
|
||||
// Alignment
|
||||
horizontalAlignment: Text.AlignHCenter;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
onLinkActivated: {
|
||||
root.activeView = "firstUseTutorial";
|
||||
}
|
||||
}
|
||||
|
||||
RalewaySemiBold {
|
||||
id: myPurchasesLink;
|
||||
|
@ -618,7 +659,7 @@ Rectangle {
|
|||
// Text size
|
||||
size: 20;
|
||||
// Anchors
|
||||
anchors.top: noPermissionText.visible ? noPermissionText.bottom : rezNowButton.bottom;
|
||||
anchors.top: explainRezText.visible ? explainRezText.bottom : (noPermissionText.visible ? noPermissionText.bottom : rezNowButton.bottom);
|
||||
anchors.topMargin: 40;
|
||||
height: paintedHeight;
|
||||
anchors.left: parent.left;
|
||||
|
|
|
@ -25,7 +25,13 @@ Rectangle {
|
|||
HifiConstants { id: hifi; }
|
||||
|
||||
id: root;
|
||||
property int activeView: 1;
|
||||
property int activeView: 1;
|
||||
|
||||
onVisibleChanged: {
|
||||
if (visible) {
|
||||
root.activeView = 1;
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
anchors.fill: parent;
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 81 KiB |
|
@ -241,7 +241,7 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
|
||||
FirstUseTutorial {
|
||||
HifiCommerceCommon.FirstUseTutorial {
|
||||
id: firstUseTutorial;
|
||||
z: 999;
|
||||
visible: root.activeView === "firstUseTutorial";
|
||||
|
|
|
@ -25,6 +25,7 @@ Item {
|
|||
|
||||
id: root;
|
||||
property string keyFilePath;
|
||||
property bool showDebugButtons: true;
|
||||
|
||||
Hifi.QmlCommerce {
|
||||
id: commerce;
|
||||
|
@ -56,6 +57,7 @@ Item {
|
|||
}
|
||||
HifiControlsUit.Button {
|
||||
id: clearCachedPassphraseButton;
|
||||
visible: root.showDebugButtons;
|
||||
color: hifi.buttons.black;
|
||||
colorScheme: hifi.colorSchemes.dark;
|
||||
anchors.top: parent.top;
|
||||
|
@ -71,6 +73,7 @@ Item {
|
|||
}
|
||||
HifiControlsUit.Button {
|
||||
id: resetButton;
|
||||
visible: root.showDebugButtons;
|
||||
color: hifi.buttons.red;
|
||||
colorScheme: hifi.colorSchemes.dark;
|
||||
anchors.top: clearCachedPassphraseButton.top;
|
||||
|
@ -95,12 +98,12 @@ Item {
|
|||
ListElement {
|
||||
isExpanded: false;
|
||||
question: "Where are my private keys stored?"
|
||||
answer: qsTr('By default, your private keys are <b>only stored on your hard drive</b> in High Fidelity Interface\'s AppData directory.<br><br><b><font color="#0093C5"><a href="#privateKeyPath">Tap here to open the file path of your hifikey in your file explorer.</a></font></b>');
|
||||
answer: qsTr('By default, your private keys are <b>only stored on your hard drive</b> in High Fidelity Interface\'s AppData directory.<br><br><b><font color="#0093C5"><a href="#privateKeyPath">Tap here to open the folder where your HifiKeys are stored on your main display.</a></font></b>');
|
||||
}
|
||||
ListElement {
|
||||
isExpanded: false;
|
||||
question: "How can I backup my private keys?"
|
||||
answer: qsTr('You may backup the file containing your private keys by copying it to a USB flash drive, or to a service like Dropbox or Google Drive.<br><br>Restore your backup by replacing the file in Interface\'s AppData directory with your backed-up copy.<br><br><b><font color="#0093C5"><a href="#privateKeyPath">Tap here to open the file path of your hifikey in your file explorer.</a></font></b>');
|
||||
answer: qsTr('You may backup the file containing your private keys by copying it to a USB flash drive, or to a service like Dropbox or Google Drive.<br><br>Restore your backup by replacing the file in Interface\'s AppData directory with your backed-up copy.<br><br><b><font color="#0093C5"><a href="#privateKeyPath">Tap here to open the folder where your HifiKeys are stored on your main display.</a></font></b>');
|
||||
}
|
||||
ListElement {
|
||||
isExpanded: false;
|
||||
|
|
|
@ -25,7 +25,7 @@ Item {
|
|||
HifiConstants { id: hifi; }
|
||||
|
||||
id: root;
|
||||
z: 998;
|
||||
z: 997;
|
||||
property bool keyboardRaised: false;
|
||||
property string titleBarIcon: "";
|
||||
property string titleBarText: "";
|
||||
|
@ -350,7 +350,7 @@ Item {
|
|||
|
||||
Item {
|
||||
id: keyboardContainer;
|
||||
z: 999;
|
||||
z: 998;
|
||||
visible: keyboard.raised;
|
||||
property bool punctuationMode: false;
|
||||
anchors {
|
||||
|
@ -361,11 +361,13 @@ Item {
|
|||
|
||||
Image {
|
||||
id: lowerKeyboardButton;
|
||||
z: 999;
|
||||
source: "images/lowerKeyboard.png";
|
||||
anchors.horizontalCenter: parent.horizontalCenter;
|
||||
anchors.bottom: keyboard.top;
|
||||
height: 30;
|
||||
width: 120;
|
||||
anchors.right: keyboard.right;
|
||||
anchors.top: keyboard.showMirrorText ? keyboard.top : undefined;
|
||||
anchors.bottom: keyboard.showMirrorText ? undefined : keyboard.bottom;
|
||||
height: 50;
|
||||
width: 60;
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent;
|
||||
|
|
|
@ -290,7 +290,17 @@ Item {
|
|||
id: removeHmdContainer;
|
||||
z: 998;
|
||||
visible: false;
|
||||
color: hifi.colors.blueHighlight;
|
||||
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0.2;
|
||||
color: hifi.colors.baseGrayHighlight;
|
||||
}
|
||||
GradientStop {
|
||||
position: 1.0;
|
||||
color: hifi.colors.baseGrayShadow;
|
||||
}
|
||||
}
|
||||
anchors.fill: backupInstructionsButton;
|
||||
radius: 5;
|
||||
MouseArea {
|
||||
|
|
|
@ -165,7 +165,7 @@ Rectangle {
|
|||
WalletSetup {
|
||||
id: walletSetup;
|
||||
visible: root.activeView === "walletSetup";
|
||||
z: 998;
|
||||
z: 997;
|
||||
anchors.fill: parent;
|
||||
|
||||
Connections {
|
||||
|
@ -192,7 +192,7 @@ Rectangle {
|
|||
PassphraseChange {
|
||||
id: passphraseChange;
|
||||
visible: root.activeView === "passphraseChange";
|
||||
z: 998;
|
||||
z: 997;
|
||||
anchors.top: titleBarContainer.bottom;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
|
@ -217,7 +217,7 @@ Rectangle {
|
|||
SecurityImageChange {
|
||||
id: securityImageChange;
|
||||
visible: root.activeView === "securityImageChange";
|
||||
z: 998;
|
||||
z: 997;
|
||||
anchors.top: titleBarContainer.bottom;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
|
@ -653,7 +653,7 @@ Rectangle {
|
|||
|
||||
Item {
|
||||
id: keyboardContainer;
|
||||
z: 999;
|
||||
z: 998;
|
||||
visible: keyboard.raised;
|
||||
property bool punctuationMode: false;
|
||||
anchors {
|
||||
|
@ -664,11 +664,13 @@ Rectangle {
|
|||
|
||||
Image {
|
||||
id: lowerKeyboardButton;
|
||||
z: 999;
|
||||
source: "images/lowerKeyboard.png";
|
||||
anchors.horizontalCenter: parent.horizontalCenter;
|
||||
anchors.bottom: keyboard.top;
|
||||
height: 30;
|
||||
width: 120;
|
||||
anchors.right: keyboard.right;
|
||||
anchors.top: keyboard.showMirrorText ? keyboard.top : undefined;
|
||||
anchors.bottom: keyboard.showMirrorText ? undefined : keyboard.bottom;
|
||||
height: 50;
|
||||
width: 60;
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent;
|
||||
|
|
|
@ -164,7 +164,7 @@ Item {
|
|||
anchors.top: parent.top;
|
||||
anchors.topMargin: 26;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 30;
|
||||
anchors.leftMargin: 20;
|
||||
anchors.right: parent.right;
|
||||
anchors.rightMargin: 30;
|
||||
height: 30;
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 721 B After Width: | Height: | Size: 1.2 KiB |
|
@ -1,5 +1,6 @@
|
|||
import QtQuick 2.0
|
||||
import QtGraphicalEffects 1.0
|
||||
import TabletScriptingInterface 1.0
|
||||
|
||||
Item {
|
||||
id: tabletButton
|
||||
|
@ -130,11 +131,13 @@ Item {
|
|||
}
|
||||
tabletButton.clicked();
|
||||
if (tabletRoot) {
|
||||
tabletRoot.playButtonClickSound();
|
||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
||||
}
|
||||
}
|
||||
onEntered: {
|
||||
tabletButton.isEntered = true;
|
||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
||||
|
||||
if (tabletButton.isActive) {
|
||||
tabletButton.state = "hover active state";
|
||||
} else {
|
||||
|
|
|
@ -9,9 +9,13 @@
|
|||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import TabletScriptingInterface 1.0
|
||||
|
||||
import "../../styles-uit"
|
||||
import "."
|
||||
|
||||
FocusScope {
|
||||
id: root
|
||||
implicitHeight: background.height
|
||||
|
@ -69,12 +73,17 @@ FocusScope {
|
|||
onImplicitWidthChanged: listView !== null ? listView.recalcSize() : 0
|
||||
|
||||
MouseArea {
|
||||
enabled: name !== "" && item.enabled
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onEntered: listView.currentIndex = index
|
||||
onEntered: {
|
||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
||||
listView.currentIndex = index
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
root.selected(item)
|
||||
tabletRoot.playButtonClickSound();
|
||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
||||
root.selected(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import QtQuick 2.0
|
||||
import Hifi 1.0
|
||||
import QtQuick.Controls 1.4
|
||||
|
||||
import "../../dialogs"
|
||||
import "../../controls"
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@ Window {
|
|||
shown: true
|
||||
width: content.width
|
||||
height: content.height
|
||||
disableFade: true
|
||||
// Disable this window from being able to call 'desktop.raise() and desktop.showDesktop'
|
||||
activator: Item {}
|
||||
property bool horizontal: true
|
||||
|
@ -127,7 +126,7 @@ Window {
|
|||
|
||||
sortButtons();
|
||||
|
||||
shown = true;
|
||||
fadeIn(null);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -143,7 +142,7 @@ Window {
|
|||
buttons.splice(index, 1);
|
||||
|
||||
if (buttons.length === 0) {
|
||||
shown = false;
|
||||
fadeOut(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,9 +36,6 @@ FocusScope {
|
|||
// Some dialogs should be destroyed when they become
|
||||
// invisible, so handle that
|
||||
onVisibleChanged: {
|
||||
if (disableFade) {
|
||||
return;
|
||||
}
|
||||
// If someone directly set the visibility to false
|
||||
// toggle it back on and use the targetVisible flag to transition
|
||||
// via fading.
|
||||
|
@ -66,9 +63,7 @@ FocusScope {
|
|||
}
|
||||
|
||||
onFadeTargetPropertyChanged: {
|
||||
if (!disableFade) {
|
||||
visible = (fadeTargetProperty != 0.0);
|
||||
}
|
||||
visible = (fadeTargetProperty != 0.0);
|
||||
}
|
||||
|
||||
function fadeIn(callback) {
|
||||
|
|
BIN
interface/resources/sounds/Button01.wav
Normal file
BIN
interface/resources/sounds/Button01.wav
Normal file
Binary file not shown.
BIN
interface/resources/sounds/Button02.wav
Normal file
BIN
interface/resources/sounds/Button02.wav
Normal file
Binary file not shown.
BIN
interface/resources/sounds/Button03.wav
Normal file
BIN
interface/resources/sounds/Button03.wav
Normal file
Binary file not shown.
BIN
interface/resources/sounds/Button04.wav
Normal file
BIN
interface/resources/sounds/Button04.wav
Normal file
Binary file not shown.
BIN
interface/resources/sounds/Button05.wav
Normal file
BIN
interface/resources/sounds/Button05.wav
Normal file
Binary file not shown.
BIN
interface/resources/sounds/Button06.wav
Normal file
BIN
interface/resources/sounds/Button06.wav
Normal file
Binary file not shown.
BIN
interface/resources/sounds/Button07.wav
Normal file
BIN
interface/resources/sounds/Button07.wav
Normal file
Binary file not shown.
BIN
interface/resources/sounds/Collapse.wav
Normal file
BIN
interface/resources/sounds/Collapse.wav
Normal file
Binary file not shown.
BIN
interface/resources/sounds/Expand.wav
Normal file
BIN
interface/resources/sounds/Expand.wav
Normal file
Binary file not shown.
BIN
interface/resources/sounds/Tab01.wav
Normal file
BIN
interface/resources/sounds/Tab01.wav
Normal file
Binary file not shown.
BIN
interface/resources/sounds/Tab02.wav
Normal file
BIN
interface/resources/sounds/Tab02.wav
Normal file
Binary file not shown.
BIN
interface/resources/sounds/Tab03.wav
Normal file
BIN
interface/resources/sounds/Tab03.wav
Normal file
Binary file not shown.
|
@ -1847,6 +1847,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
_rayPickManager.setPrecisionPicking(rayPickID, value);
|
||||
});
|
||||
|
||||
// Preload Tablet sounds
|
||||
DependencyManager::get<TabletScriptingInterface>()->preloadSounds();
|
||||
|
||||
qCDebug(interfaceapp) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(accountManager->getSessionID());
|
||||
}
|
||||
|
||||
|
@ -2324,6 +2327,8 @@ void Application::initializeUi() {
|
|||
|
||||
surfaceContext->setContextProperty("Account", AccountScriptingInterface::getInstance());
|
||||
surfaceContext->setContextProperty("Tablet", DependencyManager::get<TabletScriptingInterface>().data());
|
||||
// Tablet inteference with Tablet.qml. Need to avoid this in QML space
|
||||
surfaceContext->setContextProperty("tabletInterface", DependencyManager::get<TabletScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("DialogsManager", _dialogsManagerScriptingInterface);
|
||||
surfaceContext->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance());
|
||||
surfaceContext->setContextProperty("FaceTracker", DependencyManager::get<DdeFaceTracker>().data());
|
||||
|
@ -2392,8 +2397,8 @@ void Application::initializeUi() {
|
|||
}
|
||||
|
||||
void Application::updateCamera(RenderArgs& renderArgs) {
|
||||
PROFILE_RANGE(render, "/updateCamera");
|
||||
PerformanceTimer perfTimer("CameraUpdates");
|
||||
PROFILE_RANGE(render, __FUNCTION__);
|
||||
PerformanceTimer perfTimer("updateCamera");
|
||||
|
||||
glm::vec3 boomOffset;
|
||||
auto myAvatar = getMyAvatar();
|
||||
|
@ -2609,7 +2614,7 @@ void Application::resizeGL() {
|
|||
}
|
||||
|
||||
void Application::handleSandboxStatus(QNetworkReply* reply) {
|
||||
PROFILE_RANGE(render, "HandleSandboxStatus");
|
||||
PROFILE_RANGE(render, __FUNCTION__);
|
||||
|
||||
bool sandboxIsRunning = SandboxUtils::readStatus(reply->readAll());
|
||||
qDebug() << "HandleSandboxStatus" << sandboxIsRunning;
|
||||
|
@ -4638,7 +4643,6 @@ void Application::updateDialogs(float deltaTime) const {
|
|||
static bool domainLoadingInProgress = false;
|
||||
|
||||
void Application::update(float deltaTime) {
|
||||
|
||||
PROFILE_RANGE_EX(app, __FUNCTION__, 0xffff0000, (uint64_t)_renderFrameCount + 1);
|
||||
|
||||
if (!_physicsEnabled) {
|
||||
|
@ -4833,11 +4837,11 @@ void Application::update(float deltaTime) {
|
|||
QSharedPointer<AvatarManager> avatarManager = DependencyManager::get<AvatarManager>();
|
||||
|
||||
{
|
||||
PROFILE_RANGE_EX(simulation_physics, "Physics", 0xffff0000, (uint64_t)getActiveDisplayPlugin()->presentCount());
|
||||
PROFILE_RANGE(simulation_physics, "Physics");
|
||||
PerformanceTimer perfTimer("physics");
|
||||
if (_physicsEnabled) {
|
||||
{
|
||||
PROFILE_RANGE_EX(simulation_physics, "UpdateStates", 0xffffff00, (uint64_t)getActiveDisplayPlugin()->presentCount());
|
||||
PROFILE_RANGE(simulation_physics, "PreStep");
|
||||
|
||||
PerformanceTimer perfTimer("updateStates)");
|
||||
static VectorOfMotionStates motionStates;
|
||||
|
@ -4871,14 +4875,14 @@ void Application::update(float deltaTime) {
|
|||
});
|
||||
}
|
||||
{
|
||||
PROFILE_RANGE_EX(simulation_physics, "StepSimulation", 0xffff8000, (uint64_t)getActiveDisplayPlugin()->presentCount());
|
||||
PROFILE_RANGE(simulation_physics, "Step");
|
||||
PerformanceTimer perfTimer("stepSimulation");
|
||||
getEntities()->getTree()->withWriteLock([&] {
|
||||
_physicsEngine->stepSimulation();
|
||||
});
|
||||
}
|
||||
{
|
||||
PROFILE_RANGE_EX(simulation_physics, "HarvestChanges", 0xffffff00, (uint64_t)getActiveDisplayPlugin()->presentCount());
|
||||
PROFILE_RANGE(simulation_physics, "PostStep");
|
||||
PerformanceTimer perfTimer("harvestChanges");
|
||||
if (_physicsEngine->hasOutgoingChanges()) {
|
||||
// grab the collision events BEFORE handleOutgoingChanges() because at this point
|
||||
|
@ -4886,6 +4890,7 @@ void Application::update(float deltaTime) {
|
|||
auto& collisionEvents = _physicsEngine->getCollisionEvents();
|
||||
|
||||
getEntities()->getTree()->withWriteLock([&] {
|
||||
PROFILE_RANGE(simulation_physics, "Harvest");
|
||||
PerformanceTimer perfTimer("handleOutgoingChanges");
|
||||
|
||||
const VectorOfMotionStates& outgoingChanges = _physicsEngine->getChangedMotionStates();
|
||||
|
@ -4898,18 +4903,25 @@ void Application::update(float deltaTime) {
|
|||
|
||||
if (!_aboutToQuit) {
|
||||
// handleCollisionEvents() AFTER handleOutgoinChanges()
|
||||
PerformanceTimer perfTimer("entities");
|
||||
avatarManager->handleCollisionEvents(collisionEvents);
|
||||
// Collision events (and their scripts) must not be handled when we're locked, above. (That would risk
|
||||
// deadlock.)
|
||||
_entitySimulation->handleCollisionEvents(collisionEvents);
|
||||
{
|
||||
PROFILE_RANGE(simulation_physics, "CollisionEvents");
|
||||
PerformanceTimer perfTimer("entities");
|
||||
avatarManager->handleCollisionEvents(collisionEvents);
|
||||
// Collision events (and their scripts) must not be handled when we're locked, above. (That would risk
|
||||
// deadlock.)
|
||||
_entitySimulation->handleCollisionEvents(collisionEvents);
|
||||
}
|
||||
|
||||
PROFILE_RANGE(simulation_physics, "UpdateEntities");
|
||||
// NOTE: the getEntities()->update() call below will wait for lock
|
||||
// and will simulate entity motion (the EntityTree has been given an EntitySimulation).
|
||||
getEntities()->update(true); // update the models...
|
||||
}
|
||||
|
||||
myAvatar->harvestResultsFromPhysicsSimulation(deltaTime);
|
||||
{
|
||||
PROFILE_RANGE(simulation_physics, "MyAvatar");
|
||||
myAvatar->harvestResultsFromPhysicsSimulation(deltaTime);
|
||||
}
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails) &&
|
||||
Menu::getInstance()->isOptionChecked(MenuOption::ExpandPhysicsSimulationTiming)) {
|
||||
|
@ -4928,13 +4940,13 @@ void Application::update(float deltaTime) {
|
|||
// AvatarManager update
|
||||
{
|
||||
{
|
||||
PROFILE_RANGE(simulation, "OtherAvatars");
|
||||
PerformanceTimer perfTimer("otherAvatars");
|
||||
PROFILE_RANGE_EX(simulation, "OtherAvatars", 0xffff00ff, (uint64_t)getActiveDisplayPlugin()->presentCount());
|
||||
avatarManager->updateOtherAvatars(deltaTime);
|
||||
}
|
||||
|
||||
{
|
||||
PROFILE_RANGE_EX(simulation, "MyAvatar", 0xffff00ff, (uint64_t)getActiveDisplayPlugin()->presentCount());
|
||||
PROFILE_RANGE(simulation, "MyAvatar");
|
||||
PerformanceTimer perfTimer("MyAvatar");
|
||||
qApp->updateMyAvatarLookAtPosition();
|
||||
avatarManager->updateMyAvatar(deltaTime);
|
||||
|
@ -5805,6 +5817,8 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe
|
|||
qScriptRegisterMetaType(scriptEngine.data(), wrapperToScriptValue<TabletProxy>, wrapperFromScriptValue<TabletProxy>);
|
||||
qScriptRegisterMetaType(scriptEngine.data(),
|
||||
wrapperToScriptValue<TabletButtonProxy>, wrapperFromScriptValue<TabletButtonProxy>);
|
||||
// Tablet inteference with Tablet.qml. Need to avoid this in QML space
|
||||
scriptEngine->registerGlobalObject("tabletInterface", DependencyManager::get<TabletScriptingInterface>().data());
|
||||
scriptEngine->registerGlobalObject("Tablet", DependencyManager::get<TabletScriptingInterface>().data());
|
||||
|
||||
auto toolbarScriptingInterface = DependencyManager::get<ToolbarScriptingInterface>().data();
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
//
|
||||
#include "JointRayPick.h"
|
||||
|
||||
#include "DependencyManager.h"
|
||||
#include "avatar/AvatarManager.h"
|
||||
|
||||
JointRayPick::JointRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const RayPickFilter& filter, const float maxDistance, const bool enabled) :
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#ifndef hifi_JointRayPick_h
|
||||
#define hifi_JointRayPick_h
|
||||
|
||||
#include "RayPick.h"
|
||||
#include <pointers/rays/RayPick.h>
|
||||
|
||||
class JointRayPick : public RayPick {
|
||||
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
#include "LaserPointer.h"
|
||||
|
||||
#include "Application.h"
|
||||
#include "ui/overlays/Overlay.h"
|
||||
#include "avatar/AvatarManager.h"
|
||||
#include "RayPickScriptingInterface.h"
|
||||
|
||||
LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates,
|
||||
const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool distanceScaleEnd, const bool enabled) :
|
||||
|
@ -22,9 +22,10 @@ LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& rende
|
|||
_faceAvatar(faceAvatar),
|
||||
_centerEndY(centerEndY),
|
||||
_lockEnd(lockEnd),
|
||||
_distanceScaleEnd(distanceScaleEnd)
|
||||
_distanceScaleEnd(distanceScaleEnd),
|
||||
_rayPickUID(DependencyManager::get<RayPickScriptingInterface>()->createRayPick(rayProps))
|
||||
{
|
||||
_rayPickUID = DependencyManager::get<RayPickScriptingInterface>()->createRayPick(rayProps);
|
||||
|
||||
|
||||
for (auto& state : _renderStates) {
|
||||
if (!enabled || state.first != _currentRenderState) {
|
||||
|
@ -39,7 +40,7 @@ LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& rende
|
|||
}
|
||||
|
||||
LaserPointer::~LaserPointer() {
|
||||
DependencyManager::get<RayPickScriptingInterface>()->removeRayPick(_rayPickUID);
|
||||
qApp->getRayPickManager().removeRayPick(_rayPickUID);
|
||||
|
||||
for (auto& renderState : _renderStates) {
|
||||
renderState.second.deleteOverlays();
|
||||
|
@ -50,47 +51,51 @@ LaserPointer::~LaserPointer() {
|
|||
}
|
||||
|
||||
void LaserPointer::enable() {
|
||||
QWriteLocker lock(getLock());
|
||||
DependencyManager::get<RayPickScriptingInterface>()->enableRayPick(_rayPickUID);
|
||||
_renderingEnabled = true;
|
||||
qApp->getRayPickManager().enableRayPick(_rayPickUID);
|
||||
withWriteLock([&] {
|
||||
_renderingEnabled = true;
|
||||
});
|
||||
}
|
||||
|
||||
void LaserPointer::disable() {
|
||||
QWriteLocker lock(getLock());
|
||||
DependencyManager::get<RayPickScriptingInterface>()->disableRayPick(_rayPickUID);
|
||||
_renderingEnabled = false;
|
||||
if (!_currentRenderState.empty()) {
|
||||
if (_renderStates.find(_currentRenderState) != _renderStates.end()) {
|
||||
disableRenderState(_renderStates[_currentRenderState]);
|
||||
qApp->getRayPickManager().disableRayPick(_rayPickUID);
|
||||
withWriteLock([&] {
|
||||
_renderingEnabled = false;
|
||||
if (!_currentRenderState.empty()) {
|
||||
if (_renderStates.find(_currentRenderState) != _renderStates.end()) {
|
||||
disableRenderState(_renderStates[_currentRenderState]);
|
||||
}
|
||||
if (_defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) {
|
||||
disableRenderState(_defaultRenderStates[_currentRenderState].second);
|
||||
}
|
||||
}
|
||||
if (_defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) {
|
||||
disableRenderState(_defaultRenderStates[_currentRenderState].second);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void LaserPointer::setRenderState(const std::string& state) {
|
||||
QWriteLocker lock(getLock());
|
||||
if (!_currentRenderState.empty() && state != _currentRenderState) {
|
||||
if (_renderStates.find(_currentRenderState) != _renderStates.end()) {
|
||||
disableRenderState(_renderStates[_currentRenderState]);
|
||||
withWriteLock([&] {
|
||||
if (!_currentRenderState.empty() && state != _currentRenderState) {
|
||||
if (_renderStates.find(_currentRenderState) != _renderStates.end()) {
|
||||
disableRenderState(_renderStates[_currentRenderState]);
|
||||
}
|
||||
if (_defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) {
|
||||
disableRenderState(_defaultRenderStates[_currentRenderState].second);
|
||||
}
|
||||
}
|
||||
if (_defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) {
|
||||
disableRenderState(_defaultRenderStates[_currentRenderState].second);
|
||||
}
|
||||
}
|
||||
_currentRenderState = state;
|
||||
_currentRenderState = state;
|
||||
});
|
||||
}
|
||||
|
||||
void LaserPointer::editRenderState(const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) {
|
||||
QWriteLocker lock(getLock());
|
||||
updateRenderStateOverlay(_renderStates[state].getStartID(), startProps);
|
||||
updateRenderStateOverlay(_renderStates[state].getPathID(), pathProps);
|
||||
updateRenderStateOverlay(_renderStates[state].getEndID(), endProps);
|
||||
QVariant endDim = endProps.toMap()["dimensions"];
|
||||
if (endDim.isValid()) {
|
||||
_renderStates[state].setEndDim(vec3FromVariant(endDim));
|
||||
}
|
||||
withWriteLock([&] {
|
||||
updateRenderStateOverlay(_renderStates[state].getStartID(), startProps);
|
||||
updateRenderStateOverlay(_renderStates[state].getPathID(), pathProps);
|
||||
updateRenderStateOverlay(_renderStates[state].getEndID(), endProps);
|
||||
QVariant endDim = endProps.toMap()["dimensions"];
|
||||
if (endDim.isValid()) {
|
||||
_renderStates[state].setEndDim(vec3FromVariant(endDim));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void LaserPointer::updateRenderStateOverlay(const OverlayID& id, const QVariant& props) {
|
||||
|
@ -102,8 +107,7 @@ void LaserPointer::updateRenderStateOverlay(const OverlayID& id, const QVariant&
|
|||
}
|
||||
|
||||
const RayPickResult LaserPointer::getPrevRayPickResult() {
|
||||
QReadLocker lock(getLock());
|
||||
return DependencyManager::get<RayPickScriptingInterface>()->getPrevRayPickResult(_rayPickUID);
|
||||
return qApp->getRayPickManager().getPrevRayPickResult(_rayPickUID);
|
||||
}
|
||||
|
||||
void LaserPointer::updateRenderState(const RenderState& renderState, const IntersectionType type, const float distance, const QUuid& objectID, const PickRay& pickRay, const bool defaultState) {
|
||||
|
@ -202,65 +206,45 @@ void LaserPointer::disableRenderState(const RenderState& renderState) {
|
|||
|
||||
void LaserPointer::update() {
|
||||
// This only needs to be a read lock because update won't change any of the properties that can be modified from scripts
|
||||
QReadLocker lock(getLock());
|
||||
RayPickResult prevRayPickResult = DependencyManager::get<RayPickScriptingInterface>()->getPrevRayPickResult(_rayPickUID);
|
||||
if (_renderingEnabled && !_currentRenderState.empty() && _renderStates.find(_currentRenderState) != _renderStates.end() &&
|
||||
withReadLock([&] {
|
||||
RayPickResult prevRayPickResult = qApp->getRayPickManager().getPrevRayPickResult(_rayPickUID);
|
||||
if (_renderingEnabled && !_currentRenderState.empty() && _renderStates.find(_currentRenderState) != _renderStates.end() &&
|
||||
(prevRayPickResult.type != IntersectionType::NONE || _laserLength > 0.0f || !_objectLockEnd.first.isNull())) {
|
||||
float distance = _laserLength > 0.0f ? _laserLength : prevRayPickResult.distance;
|
||||
updateRenderState(_renderStates[_currentRenderState], prevRayPickResult.type, distance, prevRayPickResult.objectID, prevRayPickResult.searchRay, false);
|
||||
disableRenderState(_defaultRenderStates[_currentRenderState].second);
|
||||
} else if (_renderingEnabled && !_currentRenderState.empty() && _defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) {
|
||||
disableRenderState(_renderStates[_currentRenderState]);
|
||||
updateRenderState(_defaultRenderStates[_currentRenderState].second, IntersectionType::NONE, _defaultRenderStates[_currentRenderState].first, QUuid(), prevRayPickResult.searchRay, true);
|
||||
} else if (!_currentRenderState.empty()) {
|
||||
disableRenderState(_renderStates[_currentRenderState]);
|
||||
disableRenderState(_defaultRenderStates[_currentRenderState].second);
|
||||
}
|
||||
float distance = _laserLength > 0.0f ? _laserLength : prevRayPickResult.distance;
|
||||
updateRenderState(_renderStates[_currentRenderState], prevRayPickResult.type, distance, prevRayPickResult.objectID, prevRayPickResult.searchRay, false);
|
||||
disableRenderState(_defaultRenderStates[_currentRenderState].second);
|
||||
} else if (_renderingEnabled && !_currentRenderState.empty() && _defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) {
|
||||
disableRenderState(_renderStates[_currentRenderState]);
|
||||
updateRenderState(_defaultRenderStates[_currentRenderState].second, IntersectionType::NONE, _defaultRenderStates[_currentRenderState].first, QUuid(), prevRayPickResult.searchRay, true);
|
||||
} else if (!_currentRenderState.empty()) {
|
||||
disableRenderState(_renderStates[_currentRenderState]);
|
||||
disableRenderState(_defaultRenderStates[_currentRenderState].second);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void LaserPointer::setPrecisionPicking(const bool precisionPicking) {
|
||||
QWriteLocker lock(getLock());
|
||||
DependencyManager::get<RayPickScriptingInterface>()->setPrecisionPicking(_rayPickUID, precisionPicking);
|
||||
qApp->getRayPickManager().setPrecisionPicking(_rayPickUID, precisionPicking);
|
||||
}
|
||||
|
||||
void LaserPointer::setLaserLength(const float laserLength) {
|
||||
QWriteLocker lock(getLock());
|
||||
_laserLength = laserLength;
|
||||
withWriteLock([&] {
|
||||
_laserLength = laserLength;
|
||||
});
|
||||
}
|
||||
|
||||
void LaserPointer::setLockEndUUID(QUuid objectID, const bool isOverlay) {
|
||||
QWriteLocker lock(getLock());
|
||||
_objectLockEnd = std::pair<QUuid, bool>(objectID, isOverlay);
|
||||
withWriteLock([&] {
|
||||
_objectLockEnd = std::pair<QUuid, bool>(objectID, isOverlay);
|
||||
});
|
||||
}
|
||||
|
||||
void LaserPointer::setIgnoreEntities(const QScriptValue& ignoreEntities) {
|
||||
QWriteLocker lock(getLock());
|
||||
DependencyManager::get<RayPickScriptingInterface>()->setIgnoreEntities(_rayPickUID, ignoreEntities);
|
||||
void LaserPointer::setIgnoreItems(const QVector<QUuid>& ignoreItems) const {
|
||||
qApp->getRayPickManager().setIgnoreItems(_rayPickUID, ignoreItems);
|
||||
}
|
||||
|
||||
void LaserPointer::setIncludeEntities(const QScriptValue& includeEntities) {
|
||||
QWriteLocker lock(getLock());
|
||||
DependencyManager::get<RayPickScriptingInterface>()->setIncludeEntities(_rayPickUID, includeEntities);
|
||||
}
|
||||
|
||||
void LaserPointer::setIgnoreOverlays(const QScriptValue& ignoreOverlays) {
|
||||
QWriteLocker lock(getLock());
|
||||
DependencyManager::get<RayPickScriptingInterface>()->setIgnoreOverlays(_rayPickUID, ignoreOverlays);
|
||||
}
|
||||
|
||||
void LaserPointer::setIncludeOverlays(const QScriptValue& includeOverlays) {
|
||||
QWriteLocker lock(getLock());
|
||||
DependencyManager::get<RayPickScriptingInterface>()->setIncludeOverlays(_rayPickUID, includeOverlays);
|
||||
}
|
||||
|
||||
void LaserPointer::setIgnoreAvatars(const QScriptValue& ignoreAvatars) {
|
||||
QWriteLocker lock(getLock());
|
||||
DependencyManager::get<RayPickScriptingInterface>()->setIgnoreAvatars(_rayPickUID, ignoreAvatars);
|
||||
}
|
||||
|
||||
void LaserPointer::setIncludeAvatars(const QScriptValue& includeAvatars) {
|
||||
QWriteLocker lock(getLock());
|
||||
DependencyManager::get<RayPickScriptingInterface>()->setIncludeAvatars(_rayPickUID, includeAvatars);
|
||||
void LaserPointer::setIncludeItems(const QVector<QUuid>& includeItems) const {
|
||||
qApp->getRayPickManager().setIncludeItems(_rayPickUID, includeItems);
|
||||
}
|
||||
|
||||
RenderState::RenderState(const OverlayID& startID, const OverlayID& pathID, const OverlayID& endID) :
|
||||
|
@ -288,4 +272,4 @@ void RenderState::deleteOverlays() {
|
|||
if (!_endID.isNull()) {
|
||||
qApp->getOverlays().deleteOverlay(_endID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,10 +12,12 @@
|
|||
#define hifi_LaserPointer_h
|
||||
|
||||
#include <QString>
|
||||
#include "glm/glm.hpp"
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <DependencyManager.h>
|
||||
#include "raypick/RayPickScriptingInterface.h"
|
||||
#include <shared/ReadWriteLockable.h>
|
||||
|
||||
#include "ui/overlays/Overlay.h"
|
||||
|
||||
class RayPickResult;
|
||||
|
||||
|
@ -49,9 +51,10 @@ private:
|
|||
};
|
||||
|
||||
|
||||
class LaserPointer {
|
||||
class LaserPointer : public ReadWriteLockable {
|
||||
|
||||
public:
|
||||
using Pointer = std::shared_ptr<LaserPointer>;
|
||||
|
||||
typedef std::unordered_map<std::string, RenderState> RenderStateMap;
|
||||
typedef std::unordered_map<std::string, std::pair<float, RenderState>> DefaultRenderStateMap;
|
||||
|
@ -73,14 +76,8 @@ public:
|
|||
void setLaserLength(const float laserLength);
|
||||
void setLockEndUUID(QUuid objectID, const bool isOverlay);
|
||||
|
||||
void setIgnoreEntities(const QScriptValue& ignoreEntities);
|
||||
void setIncludeEntities(const QScriptValue& includeEntities);
|
||||
void setIgnoreOverlays(const QScriptValue& ignoreOverlays);
|
||||
void setIncludeOverlays(const QScriptValue& includeOverlays);
|
||||
void setIgnoreAvatars(const QScriptValue& ignoreAvatars);
|
||||
void setIncludeAvatars(const QScriptValue& includeAvatars);
|
||||
|
||||
QReadWriteLock* getLock() { return &_lock; }
|
||||
void setIgnoreItems(const QVector<QUuid>& ignoreItems) const;
|
||||
void setIncludeItems(const QVector<QUuid>& includeItems) const;
|
||||
|
||||
void update();
|
||||
|
||||
|
@ -96,8 +93,7 @@ private:
|
|||
bool _distanceScaleEnd;
|
||||
std::pair<QUuid, bool> _objectLockEnd { std::pair<QUuid, bool>(QUuid(), false)};
|
||||
|
||||
QUuid _rayPickUID;
|
||||
QReadWriteLock _lock;
|
||||
const QUuid _rayPickUID;
|
||||
|
||||
void updateRenderStateOverlay(const OverlayID& id, const QVariant& props);
|
||||
void updateRenderState(const RenderState& renderState, const IntersectionType type, const float distance, const QUuid& objectID, const PickRay& pickRay, const bool defaultState);
|
||||
|
|
|
@ -12,138 +12,110 @@
|
|||
|
||||
QUuid LaserPointerManager::createLaserPointer(const QVariant& rayProps, const LaserPointer::RenderStateMap& renderStates, const LaserPointer::DefaultRenderStateMap& defaultRenderStates,
|
||||
const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool distanceScaleEnd, const bool enabled) {
|
||||
QUuid result;
|
||||
std::shared_ptr<LaserPointer> laserPointer = std::make_shared<LaserPointer>(rayProps, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, distanceScaleEnd, enabled);
|
||||
if (!laserPointer->getRayUID().isNull()) {
|
||||
QWriteLocker containsLock(&_containsLock);
|
||||
QUuid id = QUuid::createUuid();
|
||||
_laserPointers[id] = laserPointer;
|
||||
return id;
|
||||
result = QUuid::createUuid();
|
||||
withWriteLock([&] { _laserPointers[result] = laserPointer; });
|
||||
}
|
||||
return QUuid();
|
||||
return result;
|
||||
}
|
||||
|
||||
void LaserPointerManager::removeLaserPointer(const QUuid uid) {
|
||||
QWriteLocker lock(&_containsLock);
|
||||
_laserPointers.remove(uid);
|
||||
|
||||
LaserPointer::Pointer LaserPointerManager::find(const QUuid& uid) const {
|
||||
return resultWithReadLock<LaserPointer::Pointer>([&] {
|
||||
auto itr = _laserPointers.find(uid);
|
||||
if (itr != _laserPointers.end()) {
|
||||
return *itr;
|
||||
}
|
||||
return LaserPointer::Pointer();
|
||||
});
|
||||
}
|
||||
|
||||
void LaserPointerManager::enableLaserPointer(const QUuid uid) {
|
||||
QReadLocker lock(&_containsLock);
|
||||
auto laserPointer = _laserPointers.find(uid);
|
||||
if (laserPointer != _laserPointers.end()) {
|
||||
laserPointer.value()->enable();
|
||||
|
||||
void LaserPointerManager::removeLaserPointer(const QUuid& uid) {
|
||||
withWriteLock([&] {
|
||||
_laserPointers.remove(uid);
|
||||
});
|
||||
}
|
||||
|
||||
void LaserPointerManager::enableLaserPointer(const QUuid& uid) const {
|
||||
auto laserPointer = find(uid);
|
||||
if (laserPointer) {
|
||||
laserPointer->enable();
|
||||
}
|
||||
}
|
||||
|
||||
void LaserPointerManager::disableLaserPointer(const QUuid uid) {
|
||||
QReadLocker lock(&_containsLock);
|
||||
auto laserPointer = _laserPointers.find(uid);
|
||||
if (laserPointer != _laserPointers.end()) {
|
||||
laserPointer.value()->disable();
|
||||
void LaserPointerManager::disableLaserPointer(const QUuid& uid) const {
|
||||
auto laserPointer = find(uid);
|
||||
if (laserPointer) {
|
||||
laserPointer->disable();
|
||||
}
|
||||
}
|
||||
|
||||
void LaserPointerManager::setRenderState(QUuid uid, const std::string& renderState) {
|
||||
QReadLocker lock(&_containsLock);
|
||||
auto laserPointer = _laserPointers.find(uid);
|
||||
if (laserPointer != _laserPointers.end()) {
|
||||
laserPointer.value()->setRenderState(renderState);
|
||||
void LaserPointerManager::setRenderState(const QUuid& uid, const std::string& renderState) const {
|
||||
auto laserPointer = find(uid);
|
||||
if (laserPointer) {
|
||||
laserPointer->setRenderState(renderState);
|
||||
}
|
||||
}
|
||||
|
||||
void LaserPointerManager::editRenderState(QUuid uid, const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) {
|
||||
QReadLocker lock(&_containsLock);
|
||||
auto laserPointer = _laserPointers.find(uid);
|
||||
if (laserPointer != _laserPointers.end()) {
|
||||
laserPointer.value()->editRenderState(state, startProps, pathProps, endProps);
|
||||
void LaserPointerManager::editRenderState(const QUuid& uid, const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) const {
|
||||
auto laserPointer = find(uid);
|
||||
if (laserPointer) {
|
||||
laserPointer->editRenderState(state, startProps, pathProps, endProps);
|
||||
}
|
||||
}
|
||||
|
||||
const RayPickResult LaserPointerManager::getPrevRayPickResult(const QUuid uid) {
|
||||
QReadLocker lock(&_containsLock);
|
||||
auto laserPointer = _laserPointers.find(uid);
|
||||
if (laserPointer != _laserPointers.end()) {
|
||||
return laserPointer.value()->getPrevRayPickResult();
|
||||
const RayPickResult LaserPointerManager::getPrevRayPickResult(const QUuid& uid) const {
|
||||
auto laserPointer = find(uid);
|
||||
if (laserPointer) {
|
||||
return laserPointer->getPrevRayPickResult();
|
||||
}
|
||||
return RayPickResult();
|
||||
}
|
||||
|
||||
void LaserPointerManager::update() {
|
||||
QReadLocker lock(&_containsLock);
|
||||
for (QUuid& uid : _laserPointers.keys()) {
|
||||
auto laserPointer = _laserPointers.find(uid);
|
||||
laserPointer.value()->update();
|
||||
auto cachedLaserPointers = resultWithReadLock<QList<std::shared_ptr<LaserPointer>>>([&] {
|
||||
return _laserPointers.values();
|
||||
});
|
||||
|
||||
for (const auto& laserPointer : cachedLaserPointers) {
|
||||
laserPointer->update();
|
||||
}
|
||||
}
|
||||
|
||||
void LaserPointerManager::setPrecisionPicking(QUuid uid, const bool precisionPicking) {
|
||||
QReadLocker lock(&_containsLock);
|
||||
auto laserPointer = _laserPointers.find(uid);
|
||||
if (laserPointer != _laserPointers.end()) {
|
||||
laserPointer.value()->setPrecisionPicking(precisionPicking);
|
||||
void LaserPointerManager::setPrecisionPicking(const QUuid& uid, const bool precisionPicking) const {
|
||||
auto laserPointer = find(uid);
|
||||
if (laserPointer) {
|
||||
laserPointer->setPrecisionPicking(precisionPicking);
|
||||
}
|
||||
}
|
||||
|
||||
void LaserPointerManager::setLaserLength(QUuid uid, const float laserLength) {
|
||||
QReadLocker lock(&_containsLock);
|
||||
auto laserPointer = _laserPointers.find(uid);
|
||||
if (laserPointer != _laserPointers.end()) {
|
||||
laserPointer.value()->setLaserLength(laserLength);
|
||||
void LaserPointerManager::setLaserLength(const QUuid& uid, const float laserLength) const {
|
||||
auto laserPointer = find(uid);
|
||||
if (laserPointer) {
|
||||
laserPointer->setLaserLength(laserLength);
|
||||
}
|
||||
}
|
||||
|
||||
void LaserPointerManager::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) {
|
||||
QReadLocker lock(&_containsLock);
|
||||
auto laserPointer = _laserPointers.find(uid);
|
||||
if (laserPointer != _laserPointers.end()) {
|
||||
laserPointer.value()->setIgnoreEntities(ignoreEntities);
|
||||
void LaserPointerManager::setIgnoreItems(const QUuid& uid, const QVector<QUuid>& ignoreEntities) const {
|
||||
auto laserPointer = find(uid);
|
||||
if (laserPointer) {
|
||||
laserPointer->setIgnoreItems(ignoreEntities);
|
||||
}
|
||||
}
|
||||
|
||||
void LaserPointerManager::setIncludeEntities(QUuid uid, const QScriptValue& includeEntities) {
|
||||
QReadLocker lock(&_containsLock);
|
||||
auto laserPointer = _laserPointers.find(uid);
|
||||
if (laserPointer != _laserPointers.end()) {
|
||||
laserPointer.value()->setIncludeEntities(includeEntities);
|
||||
void LaserPointerManager::setIncludeItems(const QUuid& uid, const QVector<QUuid>& includeEntities) const {
|
||||
auto laserPointer = find(uid);
|
||||
if (laserPointer) {
|
||||
laserPointer->setIncludeItems(includeEntities);
|
||||
}
|
||||
}
|
||||
|
||||
void LaserPointerManager::setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays) {
|
||||
QReadLocker lock(&_containsLock);
|
||||
auto laserPointer = _laserPointers.find(uid);
|
||||
if (laserPointer != _laserPointers.end()) {
|
||||
laserPointer.value()->setIgnoreOverlays(ignoreOverlays);
|
||||
}
|
||||
}
|
||||
|
||||
void LaserPointerManager::setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays) {
|
||||
QReadLocker lock(&_containsLock);
|
||||
auto laserPointer = _laserPointers.find(uid);
|
||||
if (laserPointer != _laserPointers.end()) {
|
||||
laserPointer.value()->setIncludeOverlays(includeOverlays);
|
||||
}
|
||||
}
|
||||
|
||||
void LaserPointerManager::setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars) {
|
||||
QReadLocker lock(&_containsLock);
|
||||
auto laserPointer = _laserPointers.find(uid);
|
||||
if (laserPointer != _laserPointers.end()) {
|
||||
laserPointer.value()->setIgnoreAvatars(ignoreAvatars);
|
||||
}
|
||||
}
|
||||
|
||||
void LaserPointerManager::setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars) {
|
||||
QReadLocker lock(&_containsLock);
|
||||
auto laserPointer = _laserPointers.find(uid);
|
||||
if (laserPointer != _laserPointers.end()) {
|
||||
laserPointer.value()->setIncludeAvatars(includeAvatars);
|
||||
}
|
||||
}
|
||||
|
||||
void LaserPointerManager::setLockEndUUID(QUuid uid, QUuid objectID, const bool isOverlay) {
|
||||
QReadLocker lock(&_containsLock);
|
||||
auto laserPointer = _laserPointers.find(uid);
|
||||
if (laserPointer != _laserPointers.end()) {
|
||||
laserPointer.value()->setLockEndUUID(objectID, isOverlay);
|
||||
void LaserPointerManager::setLockEndUUID(const QUuid& uid, const QUuid& objectID, const bool isOverlay) const {
|
||||
auto laserPointer = find(uid);
|
||||
if (laserPointer) {
|
||||
laserPointer->setLockEndUUID(objectID, isOverlay);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,39 +14,38 @@
|
|||
#include <memory>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <shared/ReadWriteLockable.h>
|
||||
|
||||
#include "LaserPointer.h"
|
||||
|
||||
class RayPickResult;
|
||||
|
||||
class LaserPointerManager {
|
||||
|
||||
class LaserPointerManager : protected ReadWriteLockable {
|
||||
|
||||
public:
|
||||
QUuid createLaserPointer(const QVariant& rayProps, const LaserPointer::RenderStateMap& renderStates, const LaserPointer::DefaultRenderStateMap& defaultRenderStates,
|
||||
const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool distanceScaleEnd, const bool enabled);
|
||||
void removeLaserPointer(const QUuid uid);
|
||||
void enableLaserPointer(const QUuid uid);
|
||||
void disableLaserPointer(const QUuid uid);
|
||||
void setRenderState(QUuid uid, const std::string& renderState);
|
||||
void editRenderState(QUuid uid, const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps);
|
||||
const RayPickResult getPrevRayPickResult(const QUuid uid);
|
||||
|
||||
void setPrecisionPicking(QUuid uid, const bool precisionPicking);
|
||||
void setLaserLength(QUuid uid, const float laserLength);
|
||||
void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities);
|
||||
void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities);
|
||||
void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays);
|
||||
void setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays);
|
||||
void setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars);
|
||||
void setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars);
|
||||
void removeLaserPointer(const QUuid& uid);
|
||||
void enableLaserPointer(const QUuid& uid) const;
|
||||
void disableLaserPointer(const QUuid& uid) const;
|
||||
void setRenderState(const QUuid& uid, const std::string& renderState) const;
|
||||
void editRenderState(const QUuid& uid, const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) const;
|
||||
const RayPickResult getPrevRayPickResult(const QUuid& uid) const;
|
||||
|
||||
void setLockEndUUID(QUuid uid, QUuid objectID, const bool isOverlay);
|
||||
void setPrecisionPicking(const QUuid& uid, const bool precisionPicking) const;
|
||||
void setLaserLength(const QUuid& uid, const float laserLength) const;
|
||||
void setIgnoreItems(const QUuid& uid, const QVector<QUuid>& ignoreEntities) const;
|
||||
void setIncludeItems(const QUuid& uid, const QVector<QUuid>& includeEntities) const;
|
||||
|
||||
void setLockEndUUID(const QUuid& uid, const QUuid& objectID, const bool isOverlay) const;
|
||||
|
||||
void update();
|
||||
|
||||
private:
|
||||
LaserPointer::Pointer find(const QUuid& uid) const;
|
||||
QHash<QUuid, std::shared_ptr<LaserPointer>> _laserPointers;
|
||||
QReadWriteLock _containsLock;
|
||||
|
||||
};
|
||||
|
||||
#endif // hifi_LaserPointerManager_h
|
||||
|
|
|
@ -11,10 +11,19 @@
|
|||
|
||||
#include "LaserPointerScriptingInterface.h"
|
||||
|
||||
#include <QVariant>
|
||||
#include "GLMHelpers.h"
|
||||
#include <QtCore/QVariant>
|
||||
|
||||
QUuid LaserPointerScriptingInterface::createLaserPointer(const QVariant& properties) {
|
||||
#include <GLMHelpers.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
||||
void LaserPointerScriptingInterface::setIgnoreItems(const QUuid& uid, const QScriptValue& ignoreItems) const {
|
||||
qApp->getLaserPointerManager().setIgnoreItems(uid, qVectorQUuidFromScriptValue(ignoreItems));
|
||||
}
|
||||
void LaserPointerScriptingInterface::setIncludeItems(const QUuid& uid, const QScriptValue& includeItems) const {
|
||||
qApp->getLaserPointerManager().setIncludeItems(uid, qVectorQUuidFromScriptValue(includeItems));
|
||||
}
|
||||
|
||||
QUuid LaserPointerScriptingInterface::createLaserPointer(const QVariant& properties) const {
|
||||
QVariantMap propertyMap = properties.toMap();
|
||||
|
||||
bool faceAvatar = false;
|
||||
|
@ -74,7 +83,7 @@ QUuid LaserPointerScriptingInterface::createLaserPointer(const QVariant& propert
|
|||
return qApp->getLaserPointerManager().createLaserPointer(properties, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, distanceScaleEnd, enabled);
|
||||
}
|
||||
|
||||
void LaserPointerScriptingInterface::editRenderState(QUuid uid, const QString& renderState, const QVariant& properties) {
|
||||
void LaserPointerScriptingInterface::editRenderState(const QUuid& uid, const QString& renderState, const QVariant& properties) const {
|
||||
QVariantMap propMap = properties.toMap();
|
||||
|
||||
QVariant startProps;
|
||||
|
@ -95,7 +104,7 @@ void LaserPointerScriptingInterface::editRenderState(QUuid uid, const QString& r
|
|||
qApp->getLaserPointerManager().editRenderState(uid, renderState.toStdString(), startProps, pathProps, endProps);
|
||||
}
|
||||
|
||||
const RenderState LaserPointerScriptingInterface::buildRenderState(const QVariantMap& propMap) {
|
||||
RenderState LaserPointerScriptingInterface::buildRenderState(const QVariantMap& propMap) {
|
||||
QUuid startID;
|
||||
if (propMap["start"].isValid()) {
|
||||
QVariantMap startMap = propMap["start"].toMap();
|
||||
|
|
|
@ -22,27 +22,23 @@ class LaserPointerScriptingInterface : public QObject, public Dependency {
|
|||
SINGLETON_DEPENDENCY
|
||||
|
||||
public slots:
|
||||
Q_INVOKABLE QUuid createLaserPointer(const QVariant& properties);
|
||||
Q_INVOKABLE void enableLaserPointer(QUuid uid) { qApp->getLaserPointerManager().enableLaserPointer(uid); }
|
||||
Q_INVOKABLE void disableLaserPointer(QUuid uid) { qApp->getLaserPointerManager().disableLaserPointer(uid); }
|
||||
Q_INVOKABLE void removeLaserPointer(QUuid uid) { qApp->getLaserPointerManager().removeLaserPointer(uid); }
|
||||
Q_INVOKABLE void editRenderState(QUuid uid, const QString& renderState, const QVariant& properties);
|
||||
Q_INVOKABLE void setRenderState(QUuid uid, const QString& renderState) { qApp->getLaserPointerManager().setRenderState(uid, renderState.toStdString()); }
|
||||
Q_INVOKABLE RayPickResult getPrevRayPickResult(QUuid uid) { return qApp->getLaserPointerManager().getPrevRayPickResult(uid); }
|
||||
Q_INVOKABLE QUuid createLaserPointer(const QVariant& properties) const;
|
||||
Q_INVOKABLE void enableLaserPointer(const QUuid& uid) const { qApp->getLaserPointerManager().enableLaserPointer(uid); }
|
||||
Q_INVOKABLE void disableLaserPointer(const QUuid& uid) const { qApp->getLaserPointerManager().disableLaserPointer(uid); }
|
||||
Q_INVOKABLE void removeLaserPointer(const QUuid& uid) const { qApp->getLaserPointerManager().removeLaserPointer(uid); }
|
||||
Q_INVOKABLE void editRenderState(const QUuid& uid, const QString& renderState, const QVariant& properties) const;
|
||||
Q_INVOKABLE void setRenderState(const QUuid& uid, const QString& renderState) const { qApp->getLaserPointerManager().setRenderState(uid, renderState.toStdString()); }
|
||||
Q_INVOKABLE RayPickResult getPrevRayPickResult(QUuid uid) const { return qApp->getLaserPointerManager().getPrevRayPickResult(uid); }
|
||||
|
||||
Q_INVOKABLE void setPrecisionPicking(QUuid uid, const bool precisionPicking) { qApp->getLaserPointerManager().setPrecisionPicking(uid, precisionPicking); }
|
||||
Q_INVOKABLE void setLaserLength(QUuid uid, const float laserLength) { qApp->getLaserPointerManager().setLaserLength(uid, laserLength); }
|
||||
Q_INVOKABLE void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) { qApp->getLaserPointerManager().setIgnoreEntities(uid, ignoreEntities); }
|
||||
Q_INVOKABLE void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities) { qApp->getLaserPointerManager().setIncludeEntities(uid, includeEntities); }
|
||||
Q_INVOKABLE void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays) { qApp->getLaserPointerManager().setIgnoreOverlays(uid, ignoreOverlays); }
|
||||
Q_INVOKABLE void setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays) { qApp->getLaserPointerManager().setIncludeOverlays(uid, includeOverlays); }
|
||||
Q_INVOKABLE void setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars) { qApp->getLaserPointerManager().setIgnoreAvatars(uid, ignoreAvatars); }
|
||||
Q_INVOKABLE void setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars) { qApp->getLaserPointerManager().setIncludeAvatars(uid, includeAvatars); }
|
||||
Q_INVOKABLE void setPrecisionPicking(const QUuid& uid, bool precisionPicking) const { qApp->getLaserPointerManager().setPrecisionPicking(uid, precisionPicking); }
|
||||
Q_INVOKABLE void setLaserLength(const QUuid& uid, float laserLength) const { qApp->getLaserPointerManager().setLaserLength(uid, laserLength); }
|
||||
Q_INVOKABLE void setIgnoreItems(const QUuid& uid, const QScriptValue& ignoreEntities) const;
|
||||
Q_INVOKABLE void setIncludeItems(const QUuid& uid, const QScriptValue& includeEntities) const;
|
||||
|
||||
Q_INVOKABLE void setLockEndUUID(QUuid uid, QUuid objectID, const bool isOverlay) { qApp->getLaserPointerManager().setLockEndUUID(uid, objectID, isOverlay); }
|
||||
Q_INVOKABLE void setLockEndUUID(const QUuid& uid, const QUuid& objectID, bool isOverlay) const { qApp->getLaserPointerManager().setLockEndUUID(uid, objectID, isOverlay); }
|
||||
|
||||
private:
|
||||
const RenderState buildRenderState(const QVariantMap& propMap);
|
||||
static RenderState buildRenderState(const QVariantMap& propMap);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#ifndef hifi_MouseRayPick_h
|
||||
#define hifi_MouseRayPick_h
|
||||
|
||||
#include "RayPick.h"
|
||||
#include <pointers/rays/RayPick.h>
|
||||
|
||||
class MouseRayPick : public RayPick {
|
||||
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
//
|
||||
// RayPick.cpp
|
||||
// interface/src/raypick
|
||||
//
|
||||
// Created by Sam Gondelman 7/11/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
|
||||
//
|
||||
#include "RayPick.h"
|
||||
|
||||
RayPick::RayPick(const RayPickFilter& filter, const float maxDistance, const bool enabled) :
|
||||
_filter(filter),
|
||||
_maxDistance(maxDistance),
|
||||
_enabled(enabled)
|
||||
{
|
||||
}
|
||||
void RayPick::enable() {
|
||||
QWriteLocker lock(getLock());
|
||||
_enabled = true;
|
||||
}
|
||||
|
||||
void RayPick::disable() {
|
||||
QWriteLocker lock(getLock());
|
||||
_enabled = false;
|
||||
}
|
||||
|
||||
const RayPickResult& RayPick::getPrevRayPickResult() {
|
||||
QReadLocker lock(getLock());
|
||||
return _prevResult;
|
||||
}
|
||||
|
||||
void RayPick::setIgnoreEntities(const QScriptValue& ignoreEntities) {
|
||||
QWriteLocker lock(getLock());
|
||||
_ignoreEntities = qVectorEntityItemIDFromScriptValue(ignoreEntities);
|
||||
}
|
||||
|
||||
void RayPick::setIncludeEntities(const QScriptValue& includeEntities) {
|
||||
QWriteLocker lock(getLock());
|
||||
_includeEntities = qVectorEntityItemIDFromScriptValue(includeEntities);
|
||||
}
|
||||
|
||||
void RayPick::setIgnoreOverlays(const QScriptValue& ignoreOverlays) {
|
||||
QWriteLocker lock(getLock());
|
||||
_ignoreOverlays = qVectorOverlayIDFromScriptValue(ignoreOverlays);
|
||||
}
|
||||
|
||||
void RayPick::setIncludeOverlays(const QScriptValue& includeOverlays) {
|
||||
QWriteLocker lock(getLock());
|
||||
_includeOverlays = qVectorOverlayIDFromScriptValue(includeOverlays);
|
||||
}
|
||||
|
||||
void RayPick::setIgnoreAvatars(const QScriptValue& ignoreAvatars) {
|
||||
QWriteLocker lock(getLock());
|
||||
_ignoreAvatars = qVectorEntityItemIDFromScriptValue(ignoreAvatars);
|
||||
}
|
||||
|
||||
void RayPick::setIncludeAvatars(const QScriptValue& includeAvatars) {
|
||||
QWriteLocker lock(getLock());
|
||||
_includeAvatars = qVectorEntityItemIDFromScriptValue(includeAvatars);
|
||||
}
|
|
@ -10,6 +10,8 @@
|
|||
//
|
||||
#include "RayPickManager.h"
|
||||
|
||||
#include <pointers/rays/StaticRayPick.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "EntityScriptingInterface.h"
|
||||
#include "ui/overlays/Overlays.h"
|
||||
|
@ -18,45 +20,50 @@
|
|||
#include "DependencyManager.h"
|
||||
|
||||
#include "JointRayPick.h"
|
||||
#include "StaticRayPick.h"
|
||||
#include "MouseRayPick.h"
|
||||
|
||||
bool RayPickManager::checkAndCompareCachedResults(QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache, RayPickResult& res, const RayPickFilter::Flags& mask) {
|
||||
if (cache.contains(ray) && cache[ray].find(mask) != cache[ray].end()) {
|
||||
if (cache[ray][mask].distance < res.distance) {
|
||||
res = cache[ray][mask];
|
||||
bool RayPickManager::checkAndCompareCachedResults(QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache, RayPickResult& res, const RayCacheKey& key) {
|
||||
if (cache.contains(ray) && cache[ray].find(key) != cache[ray].end()) {
|
||||
if (cache[ray][key].distance < res.distance) {
|
||||
res = cache[ray][key];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void RayPickManager::cacheResult(const bool intersects, const RayPickResult& resTemp, const RayPickFilter::Flags& mask, RayPickResult& res, QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache) {
|
||||
void RayPickManager::cacheResult(const bool intersects, const RayPickResult& resTemp, const RayCacheKey& key, RayPickResult& res, QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache) {
|
||||
if (intersects) {
|
||||
cache[ray][mask] = resTemp;
|
||||
cache[ray][key] = resTemp;
|
||||
if (resTemp.distance < res.distance) {
|
||||
res = resTemp;
|
||||
}
|
||||
} else {
|
||||
cache[ray][mask] = RayPickResult(res.searchRay);
|
||||
cache[ray][key] = RayPickResult(res.searchRay);
|
||||
}
|
||||
}
|
||||
|
||||
void RayPickManager::update() {
|
||||
QReadLocker lock(&_containsLock);
|
||||
RayPickCache results;
|
||||
for (auto& uid : _rayPicks.keys()) {
|
||||
std::shared_ptr<RayPick> rayPick = _rayPicks[uid];
|
||||
QWriteLocker lock(rayPick->getLock());
|
||||
QHash<QUuid, RayPick::Pointer> cachedRayPicks;
|
||||
withReadLock([&] {
|
||||
cachedRayPicks = _rayPicks;
|
||||
});
|
||||
|
||||
for (const auto& uid : cachedRayPicks.keys()) {
|
||||
std::shared_ptr<RayPick> rayPick = cachedRayPicks[uid];
|
||||
if (!rayPick->isEnabled() || rayPick->getFilter().doesPickNothing() || rayPick->getMaxDistance() < 0.0f) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool valid;
|
||||
PickRay ray = rayPick->getPickRay(valid);
|
||||
PickRay ray;
|
||||
|
||||
if (!valid) {
|
||||
continue;
|
||||
{
|
||||
bool valid;
|
||||
ray = rayPick->getPickRay(valid);
|
||||
if (!valid) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
QPair<glm::vec3, glm::vec3> rayKey = QPair<glm::vec3, glm::vec3>(ray.origin, ray.direction);
|
||||
|
@ -67,16 +74,16 @@ void RayPickManager::update() {
|
|||
bool fromCache = true;
|
||||
bool invisible = rayPick->getFilter().doesPickInvisible();
|
||||
bool nonCollidable = rayPick->getFilter().doesPickNonCollidable();
|
||||
RayPickFilter::Flags entityMask = rayPick->getFilter().getEntityFlags();
|
||||
if (!checkAndCompareCachedResults(rayKey, results, res, entityMask)) {
|
||||
entityRes = DependencyManager::get<EntityScriptingInterface>()->findRayIntersectionVector(ray, !rayPick->getFilter().doesPickCourse(),
|
||||
rayPick->getIncludeEntites(), rayPick->getIgnoreEntites(), !invisible, !nonCollidable);
|
||||
RayCacheKey entityKey = { rayPick->getFilter().getEntityFlags(), rayPick->getIncludeItems(), rayPick->getIgnoreItems() };
|
||||
if (!checkAndCompareCachedResults(rayKey, results, res, entityKey)) {
|
||||
entityRes = DependencyManager::get<EntityScriptingInterface>()->findRayIntersectionVector(ray, !rayPick->getFilter().doesPickCoarse(),
|
||||
rayPick->getIncludeItemsAs<EntityItemID>(), rayPick->getIgnoreItemsAs<EntityItemID>(), !invisible, !nonCollidable);
|
||||
fromCache = false;
|
||||
}
|
||||
|
||||
if (!fromCache) {
|
||||
cacheResult(entityRes.intersects, RayPickResult(IntersectionType::ENTITY, entityRes.entityID, entityRes.distance, entityRes.intersection, ray, entityRes.surfaceNormal),
|
||||
entityMask, res, rayKey, results);
|
||||
entityKey, res, rayKey, results);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,33 +92,34 @@ void RayPickManager::update() {
|
|||
bool fromCache = true;
|
||||
bool invisible = rayPick->getFilter().doesPickInvisible();
|
||||
bool nonCollidable = rayPick->getFilter().doesPickNonCollidable();
|
||||
RayPickFilter::Flags overlayMask = rayPick->getFilter().getOverlayFlags();
|
||||
if (!checkAndCompareCachedResults(rayKey, results, res, overlayMask)) {
|
||||
overlayRes = qApp->getOverlays().findRayIntersectionVector(ray, !rayPick->getFilter().doesPickCourse(),
|
||||
rayPick->getIncludeOverlays(), rayPick->getIgnoreOverlays(), !invisible, !nonCollidable);
|
||||
RayCacheKey overlayKey = { rayPick->getFilter().getOverlayFlags(), rayPick->getIncludeItems(), rayPick->getIgnoreItems() };
|
||||
if (!checkAndCompareCachedResults(rayKey, results, res, overlayKey)) {
|
||||
overlayRes = qApp->getOverlays().findRayIntersectionVector(ray, !rayPick->getFilter().doesPickCoarse(),
|
||||
rayPick->getIncludeItemsAs<OverlayID>(), rayPick->getIgnoreItemsAs<OverlayID>(), !invisible, !nonCollidable);
|
||||
fromCache = false;
|
||||
}
|
||||
|
||||
if (!fromCache) {
|
||||
cacheResult(overlayRes.intersects, RayPickResult(IntersectionType::OVERLAY, overlayRes.overlayID, overlayRes.distance, overlayRes.intersection, ray, overlayRes.surfaceNormal),
|
||||
overlayMask, res, rayKey, results);
|
||||
overlayKey, res, rayKey, results);
|
||||
}
|
||||
}
|
||||
|
||||
if (rayPick->getFilter().doesPickAvatars()) {
|
||||
RayPickFilter::Flags avatarMask = rayPick->getFilter().getAvatarFlags();
|
||||
if (!checkAndCompareCachedResults(rayKey, results, res, avatarMask)) {
|
||||
RayToAvatarIntersectionResult avatarRes = DependencyManager::get<AvatarManager>()->findRayIntersectionVector(ray, rayPick->getIncludeAvatars(), rayPick->getIgnoreAvatars());
|
||||
cacheResult(avatarRes.intersects, RayPickResult(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.intersection, ray), avatarMask, res, rayKey, results);
|
||||
RayCacheKey avatarKey = { rayPick->getFilter().getAvatarFlags(), rayPick->getIncludeItems(), rayPick->getIgnoreItems() };
|
||||
if (!checkAndCompareCachedResults(rayKey, results, res, avatarKey)) {
|
||||
RayToAvatarIntersectionResult avatarRes = DependencyManager::get<AvatarManager>()->findRayIntersectionVector(ray,
|
||||
rayPick->getIncludeItemsAs<EntityItemID>(), rayPick->getIgnoreItemsAs<EntityItemID>());
|
||||
cacheResult(avatarRes.intersects, RayPickResult(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.intersection, ray), avatarKey, res, rayKey, results);
|
||||
}
|
||||
}
|
||||
|
||||
// Can't intersect with HUD in desktop mode
|
||||
if (rayPick->getFilter().doesPickHUD() && DependencyManager::get<HMDScriptingInterface>()->isHMDMode()) {
|
||||
RayPickFilter::Flags hudMask = rayPick->getFilter().getHUDFlags();
|
||||
if (!checkAndCompareCachedResults(rayKey, results, res, hudMask)) {
|
||||
RayCacheKey hudKey = { rayPick->getFilter().getHUDFlags(), QVector<QUuid>(), QVector<QUuid>() };
|
||||
if (!checkAndCompareCachedResults(rayKey, results, res, hudKey)) {
|
||||
glm::vec3 hudRes = DependencyManager::get<HMDScriptingInterface>()->calculateRayUICollisionPoint(ray.origin, ray.direction);
|
||||
cacheResult(true, RayPickResult(IntersectionType::HUD, 0, glm::distance(ray.origin, hudRes), hudRes, ray), hudMask, res, rayKey, results);
|
||||
cacheResult(true, RayPickResult(IntersectionType::HUD, 0, glm::distance(ray.origin, hudRes), hudRes, ray), hudKey, res, rayKey, results);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -123,109 +131,87 @@ void RayPickManager::update() {
|
|||
}
|
||||
}
|
||||
|
||||
QUuid RayPickManager::createRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const RayPickFilter& filter, const float maxDistance, const bool enabled) {
|
||||
QWriteLocker lock(&_containsLock);
|
||||
QUuid RayPickManager::createRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const RayPickFilter& filter, float maxDistance, bool enabled) {
|
||||
auto newRayPick = std::make_shared<JointRayPick>(jointName, posOffset, dirOffset, filter, maxDistance, enabled);
|
||||
QUuid id = QUuid::createUuid();
|
||||
_rayPicks[id] = std::make_shared<JointRayPick>(jointName, posOffset, dirOffset, filter, maxDistance, enabled);
|
||||
withWriteLock([&] {
|
||||
_rayPicks[id] = newRayPick;
|
||||
});
|
||||
return id;
|
||||
}
|
||||
|
||||
QUuid RayPickManager::createRayPick(const RayPickFilter& filter, const float maxDistance, const bool enabled) {
|
||||
QWriteLocker lock(&_containsLock);
|
||||
QUuid RayPickManager::createRayPick(const RayPickFilter& filter, float maxDistance, bool enabled) {
|
||||
QUuid id = QUuid::createUuid();
|
||||
_rayPicks[id] = std::make_shared<MouseRayPick>(filter, maxDistance, enabled);
|
||||
auto newRayPick = std::make_shared<MouseRayPick>(filter, maxDistance, enabled);
|
||||
withWriteLock([&] {
|
||||
_rayPicks[id] = newRayPick;
|
||||
});
|
||||
return id;
|
||||
}
|
||||
|
||||
QUuid RayPickManager::createRayPick(const glm::vec3& position, const glm::vec3& direction, const RayPickFilter& filter, const float maxDistance, const bool enabled) {
|
||||
QWriteLocker lock(&_containsLock);
|
||||
QUuid RayPickManager::createRayPick(const glm::vec3& position, const glm::vec3& direction, const RayPickFilter& filter, float maxDistance, bool enabled) {
|
||||
QUuid id = QUuid::createUuid();
|
||||
_rayPicks[id] = std::make_shared<StaticRayPick>(position, direction, filter, maxDistance, enabled);
|
||||
auto newRayPick = std::make_shared<StaticRayPick>(position, direction, filter, maxDistance, enabled);
|
||||
withWriteLock([&] {
|
||||
_rayPicks[id] = newRayPick;
|
||||
});
|
||||
return id;
|
||||
}
|
||||
|
||||
void RayPickManager::removeRayPick(const QUuid uid) {
|
||||
QWriteLocker lock(&_containsLock);
|
||||
_rayPicks.remove(uid);
|
||||
void RayPickManager::removeRayPick(const QUuid& uid) {
|
||||
withWriteLock([&] {
|
||||
_rayPicks.remove(uid);
|
||||
});
|
||||
}
|
||||
|
||||
void RayPickManager::enableRayPick(const QUuid uid) {
|
||||
QReadLocker containsLock(&_containsLock);
|
||||
auto rayPick = _rayPicks.find(uid);
|
||||
if (rayPick != _rayPicks.end()) {
|
||||
rayPick.value()->enable();
|
||||
RayPick::Pointer RayPickManager::findRayPick(const QUuid& uid) const {
|
||||
return resultWithReadLock<RayPick::Pointer>([&] {
|
||||
if (_rayPicks.contains(uid)) {
|
||||
return _rayPicks[uid];
|
||||
}
|
||||
return RayPick::Pointer();
|
||||
});
|
||||
}
|
||||
|
||||
void RayPickManager::enableRayPick(const QUuid& uid) const {
|
||||
auto rayPick = findRayPick(uid);
|
||||
if (rayPick) {
|
||||
rayPick->enable();
|
||||
}
|
||||
}
|
||||
|
||||
void RayPickManager::disableRayPick(const QUuid uid) {
|
||||
QReadLocker containsLock(&_containsLock);
|
||||
auto rayPick = _rayPicks.find(uid);
|
||||
if (rayPick != _rayPicks.end()) {
|
||||
rayPick.value()->disable();
|
||||
void RayPickManager::disableRayPick(const QUuid& uid) const {
|
||||
auto rayPick = findRayPick(uid);
|
||||
if (rayPick) {
|
||||
rayPick->disable();
|
||||
}
|
||||
}
|
||||
|
||||
const RayPickResult RayPickManager::getPrevRayPickResult(const QUuid uid) {
|
||||
QReadLocker containsLock(&_containsLock);
|
||||
auto rayPick = _rayPicks.find(uid);
|
||||
if (rayPick != _rayPicks.end()) {
|
||||
return rayPick.value()->getPrevRayPickResult();
|
||||
RayPickResult RayPickManager::getPrevRayPickResult(const QUuid& uid) const {
|
||||
auto rayPick = findRayPick(uid);
|
||||
if (rayPick) {
|
||||
return rayPick->getPrevRayPickResult();
|
||||
}
|
||||
return RayPickResult();
|
||||
}
|
||||
|
||||
void RayPickManager::setPrecisionPicking(QUuid uid, const bool precisionPicking) {
|
||||
QReadLocker containsLock(&_containsLock);
|
||||
auto rayPick = _rayPicks.find(uid);
|
||||
if (rayPick != _rayPicks.end()) {
|
||||
rayPick.value()->setPrecisionPicking(precisionPicking);
|
||||
void RayPickManager::setPrecisionPicking(const QUuid& uid, bool precisionPicking) const {
|
||||
auto rayPick = findRayPick(uid);
|
||||
if (rayPick) {
|
||||
rayPick->setPrecisionPicking(precisionPicking);
|
||||
}
|
||||
}
|
||||
|
||||
void RayPickManager::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) {
|
||||
QReadLocker containsLock(&_containsLock);
|
||||
auto rayPick = _rayPicks.find(uid);
|
||||
if (rayPick != _rayPicks.end()) {
|
||||
rayPick.value()->setIgnoreEntities(ignoreEntities);
|
||||
void RayPickManager::setIgnoreItems(const QUuid& uid, const QVector<QUuid>& ignore) const {
|
||||
auto rayPick = findRayPick(uid);
|
||||
if (rayPick) {
|
||||
rayPick->setIgnoreItems(ignore);
|
||||
}
|
||||
}
|
||||
|
||||
void RayPickManager::setIncludeEntities(QUuid uid, const QScriptValue& includeEntities) {
|
||||
QReadLocker containsLock(&_containsLock);
|
||||
auto rayPick = _rayPicks.find(uid);
|
||||
if (rayPick != _rayPicks.end()) {
|
||||
rayPick.value()->setIncludeEntities(includeEntities);
|
||||
void RayPickManager::setIncludeItems(const QUuid& uid, const QVector<QUuid>& include) const {
|
||||
auto rayPick = findRayPick(uid);
|
||||
if (rayPick) {
|
||||
rayPick->setIncludeItems(include);
|
||||
}
|
||||
}
|
||||
|
||||
void RayPickManager::setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays) {
|
||||
QReadLocker containsLock(&_containsLock);
|
||||
auto rayPick = _rayPicks.find(uid);
|
||||
if (rayPick != _rayPicks.end()) {
|
||||
rayPick.value()->setIgnoreOverlays(ignoreOverlays);
|
||||
}
|
||||
}
|
||||
|
||||
void RayPickManager::setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays) {
|
||||
QReadLocker containsLock(&_containsLock);
|
||||
auto rayPick = _rayPicks.find(uid);
|
||||
if (rayPick != _rayPicks.end()) {
|
||||
rayPick.value()->setIncludeOverlays(includeOverlays);
|
||||
}
|
||||
}
|
||||
|
||||
void RayPickManager::setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars) {
|
||||
QReadLocker containsLock(&_containsLock);
|
||||
auto rayPick = _rayPicks.find(uid);
|
||||
if (rayPick != _rayPicks.end()) {
|
||||
rayPick.value()->setIgnoreAvatars(ignoreAvatars);
|
||||
}
|
||||
}
|
||||
|
||||
void RayPickManager::setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars) {
|
||||
QReadLocker containsLock(&_containsLock);
|
||||
auto rayPick = _rayPicks.find(uid);
|
||||
if (rayPick != _rayPicks.end()) {
|
||||
rayPick.value()->setIncludeAvatars(includeAvatars);
|
||||
}
|
||||
}
|
|
@ -11,19 +11,39 @@
|
|||
#ifndef hifi_RayPickManager_h
|
||||
#define hifi_RayPickManager_h
|
||||
|
||||
#include "RayPick.h"
|
||||
|
||||
#include <memory>
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include "RegisteredMetaTypes.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <queue>
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include <RegisteredMetaTypes.h>
|
||||
#include <pointers/rays/RayPick.h>
|
||||
|
||||
|
||||
class RayPickResult;
|
||||
|
||||
class RayPickManager {
|
||||
typedef struct RayCacheKey {
|
||||
RayPickFilter::Flags mask;
|
||||
QVector<QUuid> include;
|
||||
QVector<QUuid> ignore;
|
||||
|
||||
bool operator==(const RayCacheKey& other) const {
|
||||
return (mask == other.mask && include == other.include && ignore == other.ignore);
|
||||
}
|
||||
} RayCacheKey;
|
||||
|
||||
namespace std {
|
||||
template <>
|
||||
struct hash<RayCacheKey> {
|
||||
size_t operator()(const RayCacheKey& k) const {
|
||||
return ((hash<RayPickFilter::Flags>()(k.mask) ^ (qHash(k.include) << 1)) >> 1) ^ (qHash(k.ignore) << 1);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
class RayPickManager : protected ReadWriteLockable {
|
||||
|
||||
public:
|
||||
void update();
|
||||
|
@ -31,28 +51,24 @@ public:
|
|||
QUuid createRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const RayPickFilter& filter, const float maxDistance, const bool enabled);
|
||||
QUuid createRayPick(const RayPickFilter& filter, const float maxDistance, const bool enabled);
|
||||
QUuid createRayPick(const glm::vec3& position, const glm::vec3& direction, const RayPickFilter& filter, const float maxDistance, const bool enabled);
|
||||
void removeRayPick(const QUuid uid);
|
||||
void enableRayPick(const QUuid uid);
|
||||
void disableRayPick(const QUuid uid);
|
||||
const RayPickResult getPrevRayPickResult(const QUuid uid);
|
||||
void removeRayPick(const QUuid& uid);
|
||||
void enableRayPick(const QUuid& uid) const;
|
||||
void disableRayPick(const QUuid& uid) const;
|
||||
RayPickResult getPrevRayPickResult(const QUuid& uid) const;
|
||||
|
||||
void setPrecisionPicking(QUuid uid, const bool precisionPicking);
|
||||
void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities);
|
||||
void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities);
|
||||
void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays);
|
||||
void setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays);
|
||||
void setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars);
|
||||
void setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars);
|
||||
void setPrecisionPicking(const QUuid& uid, bool precisionPicking) const;
|
||||
void setIgnoreItems(const QUuid& uid, const QVector<QUuid>& ignore) const;
|
||||
void setIncludeItems(const QUuid& uid, const QVector<QUuid>& include) const;
|
||||
|
||||
private:
|
||||
QHash<QUuid, std::shared_ptr<RayPick>> _rayPicks;
|
||||
QReadWriteLock _containsLock;
|
||||
RayPick::Pointer findRayPick(const QUuid& uid) const;
|
||||
QHash<QUuid, RayPick::Pointer> _rayPicks;
|
||||
|
||||
typedef QHash<QPair<glm::vec3, glm::vec3>, std::unordered_map<RayPickFilter::Flags, RayPickResult>> RayPickCache;
|
||||
typedef QHash<QPair<glm::vec3, glm::vec3>, std::unordered_map<RayCacheKey, RayPickResult>> RayPickCache;
|
||||
|
||||
// Returns true if this ray exists in the cache, and if it does, update res if the cached result is closer
|
||||
bool checkAndCompareCachedResults(QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache, RayPickResult& res, const RayPickFilter::Flags& mask);
|
||||
void cacheResult(const bool intersects, const RayPickResult& resTemp, const RayPickFilter::Flags& mask, RayPickResult& res, QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache);
|
||||
bool checkAndCompareCachedResults(QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache, RayPickResult& res, const RayCacheKey& key);
|
||||
void cacheResult(const bool intersects, const RayPickResult& resTemp, const RayCacheKey& key, RayPickResult& res, QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache);
|
||||
};
|
||||
|
||||
#endif // hifi_RayPickManager_h
|
|
@ -66,46 +66,30 @@ QUuid RayPickScriptingInterface::createRayPick(const QVariant& properties) {
|
|||
return QUuid();
|
||||
}
|
||||
|
||||
void RayPickScriptingInterface::enableRayPick(QUuid uid) {
|
||||
void RayPickScriptingInterface::enableRayPick(const QUuid& uid) {
|
||||
qApp->getRayPickManager().enableRayPick(uid);
|
||||
}
|
||||
|
||||
void RayPickScriptingInterface::disableRayPick(QUuid uid) {
|
||||
void RayPickScriptingInterface::disableRayPick(const QUuid& uid) {
|
||||
qApp->getRayPickManager().disableRayPick(uid);
|
||||
}
|
||||
|
||||
void RayPickScriptingInterface::removeRayPick(QUuid uid) {
|
||||
void RayPickScriptingInterface::removeRayPick(const QUuid& uid) {
|
||||
qApp->getRayPickManager().removeRayPick(uid);
|
||||
}
|
||||
|
||||
RayPickResult RayPickScriptingInterface::getPrevRayPickResult(QUuid uid) {
|
||||
RayPickResult RayPickScriptingInterface::getPrevRayPickResult(const QUuid& uid) {
|
||||
return qApp->getRayPickManager().getPrevRayPickResult(uid);
|
||||
}
|
||||
|
||||
void RayPickScriptingInterface::setPrecisionPicking(QUuid uid, const bool precisionPicking) {
|
||||
void RayPickScriptingInterface::setPrecisionPicking(const QUuid& uid, const bool precisionPicking) {
|
||||
qApp->getRayPickManager().setPrecisionPicking(uid, precisionPicking);
|
||||
}
|
||||
|
||||
void RayPickScriptingInterface::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) {
|
||||
qApp->getRayPickManager().setIgnoreEntities(uid, ignoreEntities);
|
||||
void RayPickScriptingInterface::setIgnoreItems(const QUuid& uid, const QScriptValue& ignoreItems) {
|
||||
qApp->getRayPickManager().setIgnoreItems(uid, qVectorQUuidFromScriptValue(ignoreItems));
|
||||
}
|
||||
|
||||
void RayPickScriptingInterface::setIncludeEntities(QUuid uid, const QScriptValue& includeEntities) {
|
||||
qApp->getRayPickManager().setIncludeEntities(uid, includeEntities);
|
||||
}
|
||||
|
||||
void RayPickScriptingInterface::setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays) {
|
||||
qApp->getRayPickManager().setIgnoreOverlays(uid, ignoreOverlays);
|
||||
}
|
||||
|
||||
void RayPickScriptingInterface::setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays) {
|
||||
qApp->getRayPickManager().setIncludeOverlays(uid, includeOverlays);
|
||||
}
|
||||
|
||||
void RayPickScriptingInterface::setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars) {
|
||||
qApp->getRayPickManager().setIgnoreAvatars(uid, ignoreAvatars);
|
||||
}
|
||||
|
||||
void RayPickScriptingInterface::setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars) {
|
||||
qApp->getRayPickManager().setIncludeAvatars(uid, includeAvatars);
|
||||
void RayPickScriptingInterface::setIncludeItems(const QUuid& uid, const QScriptValue& includeItems) {
|
||||
qApp->getRayPickManager().setIncludeItems(uid, qVectorQUuidFromScriptValue(includeItems));
|
||||
}
|
||||
|
|
|
@ -13,10 +13,9 @@
|
|||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include "RegisteredMetaTypes.h"
|
||||
#include "DependencyManager.h"
|
||||
|
||||
#include "RayPick.h"
|
||||
#include <RegisteredMetaTypes.h>
|
||||
#include <DependencyManager.h>
|
||||
#include <pointers/rays/RayPick.h>
|
||||
|
||||
class RayPickScriptingInterface : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
|
@ -25,7 +24,7 @@ class RayPickScriptingInterface : public QObject, public Dependency {
|
|||
Q_PROPERTY(unsigned int PICK_OVERLAYS READ PICK_OVERLAYS CONSTANT)
|
||||
Q_PROPERTY(unsigned int PICK_AVATARS READ PICK_AVATARS CONSTANT)
|
||||
Q_PROPERTY(unsigned int PICK_HUD READ PICK_HUD CONSTANT)
|
||||
Q_PROPERTY(unsigned int PICK_COURSE READ PICK_COURSE CONSTANT)
|
||||
Q_PROPERTY(unsigned int PICK_COARSE READ PICK_COARSE CONSTANT)
|
||||
Q_PROPERTY(unsigned int PICK_INCLUDE_INVISIBLE READ PICK_INCLUDE_INVISIBLE CONSTANT)
|
||||
Q_PROPERTY(unsigned int PICK_INCLUDE_NONCOLLIDABLE READ PICK_INCLUDE_NONCOLLIDABLE CONSTANT)
|
||||
Q_PROPERTY(unsigned int PICK_ALL_INTERSECTIONS READ PICK_ALL_INTERSECTIONS CONSTANT)
|
||||
|
@ -38,25 +37,21 @@ class RayPickScriptingInterface : public QObject, public Dependency {
|
|||
|
||||
public slots:
|
||||
Q_INVOKABLE QUuid createRayPick(const QVariant& properties);
|
||||
Q_INVOKABLE void enableRayPick(QUuid uid);
|
||||
Q_INVOKABLE void disableRayPick(QUuid uid);
|
||||
Q_INVOKABLE void removeRayPick(QUuid uid);
|
||||
Q_INVOKABLE RayPickResult getPrevRayPickResult(QUuid uid);
|
||||
Q_INVOKABLE void enableRayPick(const QUuid& uid);
|
||||
Q_INVOKABLE void disableRayPick(const QUuid& uid);
|
||||
Q_INVOKABLE void removeRayPick(const QUuid& uid);
|
||||
Q_INVOKABLE RayPickResult getPrevRayPickResult(const QUuid& uid);
|
||||
|
||||
Q_INVOKABLE void setPrecisionPicking(QUuid uid, const bool precisionPicking);
|
||||
Q_INVOKABLE void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities);
|
||||
Q_INVOKABLE void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities);
|
||||
Q_INVOKABLE void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays);
|
||||
Q_INVOKABLE void setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays);
|
||||
Q_INVOKABLE void setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars);
|
||||
Q_INVOKABLE void setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars);
|
||||
Q_INVOKABLE void setPrecisionPicking(const QUuid& uid, const bool precisionPicking);
|
||||
Q_INVOKABLE void setIgnoreItems(const QUuid& uid, const QScriptValue& ignoreEntities);
|
||||
Q_INVOKABLE void setIncludeItems(const QUuid& uid, const QScriptValue& includeEntities);
|
||||
|
||||
unsigned int PICK_NOTHING() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_NOTHING); }
|
||||
unsigned int PICK_NOTHING() { return 0; }
|
||||
unsigned int PICK_ENTITIES() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_ENTITIES); }
|
||||
unsigned int PICK_OVERLAYS() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_OVERLAYS); }
|
||||
unsigned int PICK_AVATARS() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_AVATARS); }
|
||||
unsigned int PICK_HUD() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_HUD); }
|
||||
unsigned int PICK_COURSE() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_COURSE); }
|
||||
unsigned int PICK_COARSE() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_COARSE); }
|
||||
unsigned int PICK_INCLUDE_INVISIBLE() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_INCLUDE_INVISIBLE); }
|
||||
unsigned int PICK_INCLUDE_NONCOLLIDABLE() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_INCLUDE_NONCOLLIDABLE); }
|
||||
unsigned int PICK_ALL_INTERSECTIONS() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_ALL_INTERSECTIONS); }
|
||||
|
|
|
@ -51,13 +51,11 @@ void Image3DOverlay::update(float deltatime) {
|
|||
_texture = DependencyManager::get<TextureCache>()->getTexture(_url);
|
||||
_textureIsLoaded = false;
|
||||
}
|
||||
#if OVERLAY_PANELS
|
||||
if (usecTimestampNow() > _transformExpiry) {
|
||||
Transform transform = getTransform();
|
||||
applyTransformTo(transform);
|
||||
setTransform(transform);
|
||||
}
|
||||
#endif
|
||||
Parent::update(deltatime);
|
||||
}
|
||||
|
||||
|
|
|
@ -257,7 +257,3 @@ bool Text3DOverlay::findRayIntersection(const glm::vec3 &origin, const glm::vec3
|
|||
return Billboard3DOverlay::findRayIntersection(origin, direction, distance, face, surfaceNormal);
|
||||
}
|
||||
|
||||
Transform Text3DOverlay::evalRenderTransform() {
|
||||
return Parent::evalRenderTransform();
|
||||
}
|
||||
|
||||
|
|
|
@ -65,9 +65,6 @@ public:
|
|||
|
||||
virtual Text3DOverlay* createClone() const override;
|
||||
|
||||
protected:
|
||||
Transform evalRenderTransform() override;
|
||||
|
||||
private:
|
||||
TextRenderer3D* _textRenderer = nullptr;
|
||||
|
||||
|
|
|
@ -63,7 +63,6 @@ static const float OPAQUE_ALPHA_THRESHOLD = 0.99f;
|
|||
|
||||
const QString Web3DOverlay::TYPE = "web3d";
|
||||
const QString Web3DOverlay::QML = "Web3DOverlay.qml";
|
||||
|
||||
Web3DOverlay::Web3DOverlay() : _dpi(DPI) {
|
||||
_touchDevice.setCapabilities(QTouchDevice::Position);
|
||||
_touchDevice.setType(QTouchDevice::TouchScreen);
|
||||
|
@ -249,6 +248,9 @@ void Web3DOverlay::setupQmlSurface() {
|
|||
|
||||
_webSurface->getSurfaceContext()->setContextProperty("pathToFonts", "../../");
|
||||
|
||||
// Tablet inteference with Tablet.qml. Need to avoid this in QML space
|
||||
_webSurface->getSurfaceContext()->setContextProperty("tabletInterface", DependencyManager::get<TabletScriptingInterface>().data());
|
||||
|
||||
tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", _webSurface.data());
|
||||
// mark the TabletProxy object as cpp ownership.
|
||||
QObject* tablet = tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system");
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "AnimUtil.h"
|
||||
#include "IKTarget.h"
|
||||
|
||||
|
||||
static int nextRigId = 1;
|
||||
static std::map<int, Rig*> rigRegistry;
|
||||
static std::mutex rigRegistryMutex;
|
||||
|
@ -999,14 +1000,13 @@ void Rig::updateAnimationStateHandlers() { // called on avatar update thread (wh
|
|||
}
|
||||
|
||||
void Rig::updateAnimations(float deltaTime, const glm::mat4& rootTransform, const glm::mat4& rigToWorldTransform) {
|
||||
|
||||
PROFILE_RANGE_EX(simulation_animation_detail, __FUNCTION__, 0xffff00ff, 0);
|
||||
PerformanceTimer perfTimer("updateAnimations");
|
||||
DETAILED_PROFILE_RANGE_EX(simulation_animation_detail, __FUNCTION__, 0xffff00ff, 0);
|
||||
DETAILED_PERFORMANCE_TIMER("updateAnimations");
|
||||
|
||||
setModelOffset(rootTransform);
|
||||
|
||||
if (_animNode && _enabledAnimations) {
|
||||
PerformanceTimer perfTimer("handleTriggers");
|
||||
DETAILED_PERFORMANCE_TIMER("handleTriggers");
|
||||
|
||||
updateAnimationStateHandlers();
|
||||
_animVars.setRigToGeometryTransform(_rigToGeometryTransform);
|
||||
|
@ -1658,7 +1658,7 @@ bool Rig::getModelRegistrationPoint(glm::vec3& modelRegistrationPointOut) const
|
|||
}
|
||||
|
||||
void Rig::applyOverridePoses() {
|
||||
PerformanceTimer perfTimer("override");
|
||||
DETAILED_PERFORMANCE_TIMER("override");
|
||||
if (_numOverrides == 0 || !_animSkeleton) {
|
||||
return;
|
||||
}
|
||||
|
@ -1675,7 +1675,7 @@ void Rig::applyOverridePoses() {
|
|||
}
|
||||
|
||||
void Rig::buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& absolutePosesOut) {
|
||||
PerformanceTimer perfTimer("buildAbsolute");
|
||||
DETAILED_PERFORMANCE_TIMER("buildAbsolute");
|
||||
if (!_animSkeleton) {
|
||||
return;
|
||||
}
|
||||
|
@ -1730,8 +1730,9 @@ void Rig::copyJointsIntoJointData(QVector<JointData>& jointDataVec) const {
|
|||
}
|
||||
|
||||
void Rig::copyJointsFromJointData(const QVector<JointData>& jointDataVec) {
|
||||
PerformanceTimer perfTimer("copyJoints");
|
||||
PROFILE_RANGE(simulation_animation_detail, "copyJoints");
|
||||
DETAILED_PROFILE_RANGE(simulation_animation_detail, "copyJoints");
|
||||
DETAILED_PERFORMANCE_TIMER("copyJoints");
|
||||
|
||||
if (!_animSkeleton) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -377,7 +377,8 @@ void FBXBaker::rewriteAndBakeSceneModels() {
|
|||
bool hasColors { mesh.colors.size() > 0 };
|
||||
bool hasTexCoords { mesh.texCoords.size() > 0 };
|
||||
bool hasTexCoords1 { mesh.texCoords1.size() > 0 };
|
||||
bool hasPerFaceMaterials { mesh.parts.size() > 1 };
|
||||
bool hasPerFaceMaterials { mesh.parts.size() > 1
|
||||
|| extractedMesh.partMaterialTextures[0].first != 0 };
|
||||
bool needsOriginalIndices { hasDeformers };
|
||||
|
||||
int normalsAttributeID { -1 };
|
||||
|
@ -594,6 +595,10 @@ void FBXBaker::rewriteAndBakeSceneTextures() {
|
|||
QString fbxTextureFileName { textureChild.properties.at(0).toByteArray() };
|
||||
QFileInfo textureFileInfo { fbxTextureFileName.replace("\\", "/") };
|
||||
|
||||
if (hasErrors()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (textureFileInfo.suffix() == BAKED_TEXTURE_EXT.mid(1)) {
|
||||
// re-baking an FBX that already references baked textures is a fail
|
||||
// so we add an error and return from here
|
||||
|
@ -602,6 +607,11 @@ void FBXBaker::rewriteAndBakeSceneTextures() {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!TextureBaker::getSupportedFormats().contains(textureFileInfo.suffix())) {
|
||||
// this is a texture format we don't bake, skip it
|
||||
handleWarning(fbxTextureFileName + " is not a bakeable texture format");
|
||||
continue;
|
||||
}
|
||||
|
||||
// make sure this texture points to something and isn't one we've already re-mapped
|
||||
if (!textureFileInfo.filePath().isEmpty()) {
|
||||
|
|
|
@ -164,6 +164,8 @@ void EntityTreeRenderer::shutdown() {
|
|||
}
|
||||
|
||||
void EntityTreeRenderer::addPendingEntities(const render::ScenePointer& scene, render::Transaction& transaction) {
|
||||
PROFILE_RANGE_EX(simulation_physics, "Add", 0xffff00ff, (uint64_t)_entitiesToAdd.size());
|
||||
PerformanceTimer pt("add");
|
||||
// Clear any expired entities
|
||||
// FIXME should be able to use std::remove_if, but it fails due to some
|
||||
// weird compilation error related to EntityItemID assignment operators
|
||||
|
@ -207,6 +209,8 @@ void EntityTreeRenderer::addPendingEntities(const render::ScenePointer& scene, r
|
|||
}
|
||||
|
||||
void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene, render::Transaction& transaction) {
|
||||
PROFILE_RANGE_EX(simulation_physics, "Change", 0xffff00ff, (uint64_t)_changedEntities.size());
|
||||
PerformanceTimer pt("change");
|
||||
std::unordered_set<EntityItemID> changedEntities;
|
||||
_changedEntitiesGuard.withWriteLock([&] {
|
||||
#if 0
|
||||
|
@ -227,6 +231,7 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene
|
|||
}
|
||||
|
||||
if (!_renderablesToUpdate.empty()) {
|
||||
PROFILE_RANGE_EX(simulation_physics, "UpdateRenderables", 0xffff00ff, (uint64_t)_renderablesToUpdate.size());
|
||||
for (const auto& entry : _renderablesToUpdate) {
|
||||
const auto& renderable = entry.second;
|
||||
renderable->updateInScene(scene, transaction);
|
||||
|
@ -236,6 +241,7 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene
|
|||
}
|
||||
|
||||
void EntityTreeRenderer::update(bool simulate) {
|
||||
PROFILE_RANGE(simulation_physics, "ETR::update");
|
||||
PerformanceTimer perfTimer("ETRupdate");
|
||||
if (_tree && !_shuttingDown) {
|
||||
EntityTreePointer tree = std::static_pointer_cast<EntityTree>(_tree);
|
||||
|
@ -243,22 +249,14 @@ void EntityTreeRenderer::update(bool simulate) {
|
|||
|
||||
// Update the rendereable entities as needed
|
||||
{
|
||||
PROFILE_RANGE(simulation_physics, "Scene");
|
||||
PerformanceTimer sceneTimer("scene");
|
||||
auto scene = _viewState->getMain3DScene();
|
||||
if (scene) {
|
||||
render::Transaction transaction;
|
||||
{
|
||||
PerformanceTimer pt("add");
|
||||
addPendingEntities(scene, transaction);
|
||||
}
|
||||
{
|
||||
PerformanceTimer pt("change");
|
||||
updateChangedEntities(scene, transaction);
|
||||
}
|
||||
{
|
||||
PerformanceTimer pt("enqueue");
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
addPendingEntities(scene, transaction);
|
||||
updateChangedEntities(scene, transaction);
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -340,7 +338,8 @@ bool EntityTreeRenderer::findBestZoneAndMaybeContainingEntities(QVector<EntityIt
|
|||
}
|
||||
|
||||
bool EntityTreeRenderer::checkEnterLeaveEntities() {
|
||||
PerformanceTimer perfTimer("checkEnterLeaveEntities");
|
||||
PROFILE_RANGE(simulation_physics, "EnterLeave");
|
||||
PerformanceTimer perfTimer("enterLeave");
|
||||
auto now = usecTimestampNow();
|
||||
bool didUpdate = false;
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "RenderableWebEntityItem.h"
|
||||
#include "RenderableZoneEntityItem.h"
|
||||
|
||||
|
||||
using namespace render;
|
||||
using namespace render::entities;
|
||||
|
||||
|
@ -271,6 +272,7 @@ void EntityRenderer::removeFromScene(const ScenePointer& scene, Transaction& tra
|
|||
}
|
||||
|
||||
void EntityRenderer::updateInScene(const ScenePointer& scene, Transaction& transaction) {
|
||||
DETAILED_PROFILE_RANGE(simulation_physics, __FUNCTION__);
|
||||
if (!isValidRenderItem()) {
|
||||
return;
|
||||
}
|
||||
|
@ -330,6 +332,7 @@ bool EntityRenderer::needsRenderUpdateFromEntity(const EntityItemPointer& entity
|
|||
}
|
||||
|
||||
void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transaction& transaction, const EntityItemPointer& entity) {
|
||||
DETAILED_PROFILE_RANGE(simulation_physics, __FUNCTION__);
|
||||
withWriteLock([&] {
|
||||
auto transparent = isTransparent();
|
||||
if (_prevIsTransparent && !transparent) {
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "EntityTreeRenderer.h"
|
||||
#include "EntitiesRendererLogging.h"
|
||||
|
||||
|
||||
static CollisionRenderMeshCache collisionMeshCache;
|
||||
|
||||
void ModelEntityWrapper::setModel(const ModelPointer& model) {
|
||||
|
@ -107,6 +108,7 @@ QVariantMap parseTexturesToMap(QString textures, const QVariantMap& defaultTextu
|
|||
}
|
||||
|
||||
void RenderableModelEntityItem::doInitialModelSimulation() {
|
||||
DETAILED_PROFILE_RANGE(simulation_physics, __FUNCTION__);
|
||||
ModelPointer model = getModel();
|
||||
if (!model) {
|
||||
return;
|
||||
|
@ -123,11 +125,11 @@ void RenderableModelEntityItem::doInitialModelSimulation() {
|
|||
model->setSnapModelToRegistrationPoint(true, getRegistrationPoint());
|
||||
model->setRotation(getRotation());
|
||||
model->setTranslation(getPosition());
|
||||
{
|
||||
PerformanceTimer perfTimer("model->simulate");
|
||||
|
||||
if (_needsInitialSimulation) {
|
||||
model->simulate(0.0f);
|
||||
_needsInitialSimulation = false;
|
||||
}
|
||||
_needsInitialSimulation = false;
|
||||
}
|
||||
|
||||
void RenderableModelEntityItem::autoResizeJointArrays() {
|
||||
|
@ -138,6 +140,7 @@ void RenderableModelEntityItem::autoResizeJointArrays() {
|
|||
}
|
||||
|
||||
bool RenderableModelEntityItem::needsUpdateModelBounds() const {
|
||||
DETAILED_PROFILE_RANGE(simulation_physics, __FUNCTION__);
|
||||
ModelPointer model = getModel();
|
||||
if (!hasModel() || !model) {
|
||||
return false;
|
||||
|
@ -151,7 +154,7 @@ bool RenderableModelEntityItem::needsUpdateModelBounds() const {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (isMovingRelativeToParent() || isAnimatingSomething()) {
|
||||
if (isAnimatingSomething()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -178,13 +181,61 @@ bool RenderableModelEntityItem::needsUpdateModelBounds() const {
|
|||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return model->needsReload();
|
||||
}
|
||||
|
||||
void RenderableModelEntityItem::updateModelBounds() {
|
||||
if (needsUpdateModelBounds()) {
|
||||
doInitialModelSimulation();
|
||||
DETAILED_PROFILE_RANGE(simulation_physics, "updateModelBounds");
|
||||
|
||||
if (!_dimensionsInitialized || !hasModel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ModelPointer model = getModel();
|
||||
if (!model || !model->isLoaded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool updateRenderItems = false;
|
||||
if (model->needsReload()) {
|
||||
model->updateGeometry();
|
||||
updateRenderItems = true;
|
||||
}
|
||||
|
||||
if (model->getScaleToFitDimensions() != getDimensions() ||
|
||||
model->getRegistrationPoint() != getRegistrationPoint()) {
|
||||
// The machinery for updateModelBounds will give existing models the opportunity to fix their
|
||||
// translation/rotation/scale/registration. The first two are straightforward, but the latter two
|
||||
// have guards to make sure they don't happen after they've already been set. Here we reset those guards.
|
||||
// This doesn't cause the entity values to change -- it just allows the model to match once it comes in.
|
||||
model->setScaleToFit(false, getDimensions());
|
||||
model->setSnapModelToRegistrationPoint(false, getRegistrationPoint());
|
||||
|
||||
// now recalculate the bounds and registration
|
||||
model->setScaleToFit(true, getDimensions());
|
||||
model->setSnapModelToRegistrationPoint(true, getRegistrationPoint());
|
||||
updateRenderItems = true;
|
||||
}
|
||||
|
||||
bool success;
|
||||
auto transform = getTransform(success);
|
||||
if (success && (model->getTranslation() != transform.getTranslation() ||
|
||||
model->getRotation() != transform.getRotation())) {
|
||||
model->setTransformNoUpdateRenderItems(transform);
|
||||
updateRenderItems = true;
|
||||
}
|
||||
|
||||
if (_needsInitialSimulation || _needsJointSimulation || isAnimatingSomething()) {
|
||||
// NOTE: on isAnimatingSomething() we need to call Model::simulate() which calls Rig::updateRig()
|
||||
// TODO: there is opportunity to further optimize the isAnimatingSomething() case.
|
||||
model->simulate(0.0f);
|
||||
_needsInitialSimulation = false;
|
||||
_needsJointSimulation = false;
|
||||
updateRenderItems = true;
|
||||
}
|
||||
|
||||
if (updateRenderItems) {
|
||||
model->updateRenderItems();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -293,7 +344,7 @@ bool RenderableModelEntityItem::isReadyToComputeShape() const {
|
|||
// we have both URLs AND both geometries AND they are both fully loaded.
|
||||
if (_needsInitialSimulation) {
|
||||
// the _model's offset will be wrong until _needsInitialSimulation is false
|
||||
PerformanceTimer perfTimer("_model->simulate");
|
||||
DETAILED_PERFORMANCE_TIMER("_model->simulate");
|
||||
const_cast<RenderableModelEntityItem*>(this)->doInitialModelSimulation();
|
||||
}
|
||||
return true;
|
||||
|
@ -839,7 +890,7 @@ void RenderableModelEntityItem::setJointTranslationsSet(const QVector<bool>& tra
|
|||
}
|
||||
|
||||
void RenderableModelEntityItem::locationChanged(bool tellPhysics) {
|
||||
PerformanceTimer pertTimer("locationChanged");
|
||||
DETAILED_PERFORMANCE_TIMER("locationChanged");
|
||||
EntityItem::locationChanged(tellPhysics);
|
||||
auto model = getModel();
|
||||
if (model && model->isLoaded()) {
|
||||
|
@ -880,7 +931,6 @@ void RenderableModelEntityItem::copyAnimationJointDataToModel() {
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
// relay any inbound joint changes from scripts/animation/network to the model/rig
|
||||
_jointDataLock.withWriteLock([&] {
|
||||
for (int index = 0; index < _localJointData.size(); ++index) {
|
||||
|
@ -897,15 +947,11 @@ void RenderableModelEntityItem::copyAnimationJointDataToModel() {
|
|||
});
|
||||
}
|
||||
|
||||
bool RenderableModelEntityItem::isAnimatingSomething() const {
|
||||
return !getAnimationURL().isEmpty() && getAnimationIsPlaying() && getAnimationFPS() != 0.0f;
|
||||
}
|
||||
|
||||
using namespace render;
|
||||
using namespace render::entities;
|
||||
|
||||
ItemKey ModelEntityRenderer::getKey() {
|
||||
return ItemKey::Builder().withTypeMeta();
|
||||
return ItemKey::Builder().withTypeMeta().withTypeShape();
|
||||
}
|
||||
|
||||
uint32_t ModelEntityRenderer::metaFetchMetaSubItems(ItemIDs& subItems) {
|
||||
|
@ -1124,6 +1170,7 @@ bool ModelEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoin
|
|||
}
|
||||
|
||||
void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
||||
DETAILED_PROFILE_RANGE(simulation_physics, __FUNCTION__);
|
||||
if (_hasModel != entity->hasModel()) {
|
||||
_hasModel = entity->hasModel();
|
||||
}
|
||||
|
@ -1202,9 +1249,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
}
|
||||
}
|
||||
|
||||
if (entity->needsUpdateModelBounds()) {
|
||||
entity->updateModelBounds();
|
||||
}
|
||||
entity->updateModelBounds();
|
||||
|
||||
if (model->isVisible() != _visible) {
|
||||
// FIXME: this seems like it could be optimized if we tracked our last known visible state in
|
||||
|
@ -1212,13 +1257,16 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
// so most of the time we don't do anything in this function.
|
||||
model->setVisibleInScene(_visible, scene);
|
||||
}
|
||||
// TODO? early exit here when not visible?
|
||||
|
||||
//entity->doInitialModelSimulation();
|
||||
if (model->needsFixupInScene()) {
|
||||
model->removeFromScene(scene, transaction);
|
||||
render::Item::Status::Getters statusGetters;
|
||||
makeStatusGetters(entity, statusGetters);
|
||||
model->addToScene(scene, transaction, statusGetters);
|
||||
{
|
||||
DETAILED_PROFILE_RANGE(simulation_physics, "Fixup");
|
||||
if (model->needsFixupInScene()) {
|
||||
model->removeFromScene(scene, transaction);
|
||||
render::Item::Status::Getters statusGetters;
|
||||
makeStatusGetters(entity, statusGetters);
|
||||
model->addToScene(scene, transaction, statusGetters);
|
||||
}
|
||||
}
|
||||
|
||||
// When the individual mesh parts of a model finish fading, they will mark their Model as needing updating
|
||||
|
@ -1227,16 +1275,20 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
model->updateRenderItems();
|
||||
}
|
||||
|
||||
// make a copy of the animation properites
|
||||
auto newAnimationProperties = entity->getAnimationProperties();
|
||||
if (newAnimationProperties != _renderAnimationProperties) {
|
||||
withWriteLock([&] {
|
||||
_renderAnimationProperties = newAnimationProperties;
|
||||
_currentFrame = _renderAnimationProperties.getCurrentFrame();
|
||||
});
|
||||
{
|
||||
DETAILED_PROFILE_RANGE(simulation_physics, "CheckAnimation");
|
||||
// make a copy of the animation properites
|
||||
auto newAnimationProperties = entity->getAnimationProperties();
|
||||
if (newAnimationProperties != _renderAnimationProperties) {
|
||||
withWriteLock([&] {
|
||||
_renderAnimationProperties = newAnimationProperties;
|
||||
_currentFrame = _renderAnimationProperties.getCurrentFrame();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (_animating) {
|
||||
DETAILED_PROFILE_RANGE(simulation_physics, "Animate");
|
||||
if (!jointsMapped()) {
|
||||
mapJoints(entity, model->getJointNames());
|
||||
}
|
||||
|
@ -1247,15 +1299,16 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
|
||||
// NOTE: this only renders the "meta" portion of the Model, namely it renders debugging items
|
||||
void ModelEntityRenderer::doRender(RenderArgs* args) {
|
||||
PROFILE_RANGE(render_detail, "MetaModelRender");
|
||||
PerformanceTimer perfTimer("RMEIrender");
|
||||
DETAILED_PROFILE_RANGE(render_detail, "MetaModelRender");
|
||||
DETAILED_PERFORMANCE_TIMER("RMEIrender");
|
||||
|
||||
ModelPointer model;
|
||||
withReadLock([&]{
|
||||
model = _model;
|
||||
});
|
||||
|
||||
if (_model && _model->didVisualGeometryRequestFail()) {
|
||||
// If we don't have a model, or the model doesn't have visual geometry, render our bounding box as green wireframe
|
||||
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
|
||||
|
|
|
@ -108,7 +108,6 @@ public:
|
|||
|
||||
private:
|
||||
bool needsUpdateModelBounds() const;
|
||||
bool isAnimatingSomething() const;
|
||||
void autoResizeJointArrays();
|
||||
void copyAnimationJointDataToModel();
|
||||
|
||||
|
|
|
@ -96,6 +96,7 @@ PolyLineEntityRenderer::PolyLineEntityRenderer(const EntityItemPointer& entity)
|
|||
polylineFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), offsetof(Vertex, position));
|
||||
polylineFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), offsetof(Vertex, normal));
|
||||
polylineFormat->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), offsetof(Vertex, uv));
|
||||
polylineFormat->setAttribute(gpu::Stream::COLOR, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RGB), offsetof(Vertex, color));
|
||||
});
|
||||
|
||||
PolyLineUniforms uniforms;
|
||||
|
@ -116,7 +117,8 @@ bool PolyLineEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityP
|
|||
entity->pointsChanged() ||
|
||||
entity->strokeWidthsChanged() ||
|
||||
entity->normalsChanged() ||
|
||||
entity->texturesChanged()
|
||||
entity->texturesChanged() ||
|
||||
entity->strokeColorsChanged()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -129,9 +131,11 @@ void PolyLineEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer&
|
|||
if (!textures.isEmpty()) {
|
||||
entityTextures = QUrl(textures);
|
||||
}
|
||||
_texture = DependencyManager::get<TextureCache>()->getTexture(entityTextures);
|
||||
}
|
||||
|
||||
if (!_texture || _texture->getURL() != entityTextures) {
|
||||
|
||||
|
||||
if (!_texture) {
|
||||
_texture = DependencyManager::get<TextureCache>()->getTexture(entityTextures);
|
||||
}
|
||||
}
|
||||
|
@ -143,6 +147,10 @@ void PolyLineEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPo
|
|||
auto pointsChanged = entity->pointsChanged();
|
||||
auto strokeWidthsChanged = entity->strokeWidthsChanged();
|
||||
auto normalsChanged = entity->normalsChanged();
|
||||
auto strokeColorsChanged = entity->strokeColorsChanged();
|
||||
|
||||
|
||||
bool isUVModeStretch = entity->getIsUVModeStretch();
|
||||
entity->resetPolyLineChanged();
|
||||
|
||||
_polylineTransform = Transform();
|
||||
|
@ -158,10 +166,14 @@ void PolyLineEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPo
|
|||
if (normalsChanged) {
|
||||
_lastNormals = entity->getNormals();
|
||||
}
|
||||
if (pointsChanged || strokeWidthsChanged || normalsChanged) {
|
||||
if (strokeColorsChanged) {
|
||||
_lastStrokeColors = entity->getStrokeColors();
|
||||
_lastStrokeColors = _lastNormals.size() == _lastStrokeColors.size() ? _lastStrokeColors : QVector<glm::vec3>({ toGlm(entity->getXColor()) });
|
||||
}
|
||||
if (pointsChanged || strokeWidthsChanged || normalsChanged || strokeColorsChanged) {
|
||||
_empty = std::min(_lastPoints.size(), std::min(_lastNormals.size(), _lastStrokeWidths.size())) < 2;
|
||||
if (!_empty) {
|
||||
updateGeometry(updateVertices(_lastPoints, _lastNormals, _lastStrokeWidths));
|
||||
updateGeometry(updateVertices(_lastPoints, _lastNormals, _lastStrokeWidths, _lastStrokeColors, isUVModeStretch, _textureAspectRatio));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -175,7 +187,12 @@ void PolyLineEntityRenderer::updateGeometry(const std::vector<Vertex>& vertices)
|
|||
_verticesBuffer->setSubData(0, vertices);
|
||||
}
|
||||
|
||||
std::vector<PolyLineEntityRenderer::Vertex> PolyLineEntityRenderer::updateVertices(const QVector<glm::vec3>& points, const QVector<glm::vec3>& normals, const QVector<float>& strokeWidths) {
|
||||
std::vector<PolyLineEntityRenderer::Vertex> PolyLineEntityRenderer::updateVertices(const QVector<glm::vec3>& points,
|
||||
const QVector<glm::vec3>& normals,
|
||||
const QVector<float>& strokeWidths,
|
||||
const QVector<glm::vec3>& strokeColors,
|
||||
const bool isUVModeStretch,
|
||||
const float textureAspectRatio) {
|
||||
// Calculate the minimum vector size out of normals, points, and stroke widths
|
||||
int size = std::min(points.size(), std::min(normals.size(), strokeWidths.size()));
|
||||
|
||||
|
@ -190,10 +207,52 @@ std::vector<PolyLineEntityRenderer::Vertex> PolyLineEntityRenderer::updateVertic
|
|||
float uCoord = 0.0f;
|
||||
int finalIndex = size - 1;
|
||||
glm::vec3 binormal;
|
||||
float accumulatedDistance = 0.0f;
|
||||
float distanceToLastPoint = 0.0f;
|
||||
float accumulatedStrokeWidth = 0.0f;
|
||||
float strokeWidth = 0.0f;
|
||||
bool doesStrokeWidthVary = false;
|
||||
|
||||
|
||||
for (int i = 1; i < strokeWidths.size(); i++) {
|
||||
if (strokeWidths[i] != strokeWidths[i - 1]) {
|
||||
doesStrokeWidthVary = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i <= finalIndex; i++) {
|
||||
const float& width = strokeWidths.at(i);
|
||||
const auto& point = points.at(i);
|
||||
const auto& normal = normals.at(i);
|
||||
const auto& color = strokeColors.size() == normals.size() ? strokeColors.at(i) : strokeColors.at(0);
|
||||
int vertexIndex = i * 2;
|
||||
|
||||
|
||||
if (!isUVModeStretch && i >= 1) {
|
||||
distanceToLastPoint = glm::distance(points.at(i), points.at(i - 1));
|
||||
accumulatedDistance += distanceToLastPoint;
|
||||
strokeWidth = 2 * strokeWidths[i];
|
||||
|
||||
if (doesStrokeWidthVary) {
|
||||
//If the stroke varies along the line the texture will stretch more or less depending on the speed
|
||||
//because it looks better than using the same method as below
|
||||
accumulatedStrokeWidth += strokeWidth;
|
||||
float increaseValue = 1;
|
||||
if (accumulatedStrokeWidth != 0) {
|
||||
float newUcoord = glm::ceil(((1.0f / textureAspectRatio) * accumulatedDistance) / (accumulatedStrokeWidth / i));
|
||||
increaseValue = newUcoord - uCoord;
|
||||
}
|
||||
|
||||
increaseValue = increaseValue > 0 ? increaseValue : 1;
|
||||
uCoord += increaseValue;
|
||||
} else {
|
||||
//If the stroke width is constant then the textures should keep the aspect ratio along the line
|
||||
uCoord = ((1.0f / textureAspectRatio) * accumulatedDistance) / strokeWidth;
|
||||
}
|
||||
} else if (vertexIndex >= 2) {
|
||||
uCoord += uCoordInc;
|
||||
}
|
||||
|
||||
// For last point we can assume binormals are the same since it represents the last two vertices of quad
|
||||
if (i < finalIndex) {
|
||||
|
@ -206,11 +265,10 @@ std::vector<PolyLineEntityRenderer::Vertex> PolyLineEntityRenderer::updateVertic
|
|||
}
|
||||
}
|
||||
|
||||
const auto v1 = point + binormal;
|
||||
const auto v2 = point - binormal;
|
||||
vertices.emplace_back(v1, normal, vec2(uCoord, 0.0f));
|
||||
vertices.emplace_back(v2, normal, vec2(uCoord, 1.0f));
|
||||
uCoord += uCoordInc;
|
||||
const auto v1 = points.at(i) + binormal;
|
||||
const auto v2 = points.at(i) - binormal;
|
||||
vertices.emplace_back(v1, normal, vec2(uCoord, 0.0f), color);
|
||||
vertices.emplace_back(v2, normal, vec2(uCoord, 1.0f), color);
|
||||
}
|
||||
|
||||
return vertices;
|
||||
|
@ -235,6 +293,12 @@ void PolyLineEntityRenderer::doRender(RenderArgs* args) {
|
|||
batch.setResourceTexture(PAINTSTROKE_TEXTURE_SLOT, DependencyManager::get<TextureCache>()->getWhiteTexture());
|
||||
}
|
||||
|
||||
float textureWidth = (float)_texture->getOriginalWidth();
|
||||
float textureHeight = (float)_texture->getOriginalHeight();
|
||||
if (textureWidth != 0 && textureHeight != 0) {
|
||||
_textureAspectRatio = textureWidth / textureHeight;
|
||||
}
|
||||
|
||||
batch.setInputFormat(polylineFormat);
|
||||
batch.setInputBuffer(0, _verticesBuffer, 0, sizeof(Vertex));
|
||||
|
||||
|
@ -247,4 +311,4 @@ void PolyLineEntityRenderer::doRender(RenderArgs* args) {
|
|||
#endif
|
||||
|
||||
batch.draw(gpu::TRIANGLE_STRIP, _numVertices, 0);
|
||||
}
|
||||
}
|
|
@ -27,7 +27,9 @@ public:
|
|||
|
||||
protected:
|
||||
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
||||
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;
|
||||
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene,
|
||||
Transaction& transaction,
|
||||
const TypedEntityPointer& entity) override;
|
||||
virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
|
||||
|
||||
virtual ItemKey getKey() override;
|
||||
|
@ -38,24 +40,37 @@ protected:
|
|||
|
||||
struct Vertex {
|
||||
Vertex() {}
|
||||
Vertex(const vec3& position, const vec3& normal, const vec2& uv) : position(position), normal(normal), uv(uv) {}
|
||||
Vertex(const vec3& position, const vec3& normal, const vec2& uv, const vec3& color) : position(position),
|
||||
normal(normal),
|
||||
uv(uv),
|
||||
color(color) {}
|
||||
vec3 position;
|
||||
vec3 normal;
|
||||
vec2 uv;
|
||||
vec3 color;
|
||||
};
|
||||
|
||||
void updateGeometry(const std::vector<Vertex>& vertices);
|
||||
static std::vector<Vertex> updateVertices(const QVector<glm::vec3>& points, const QVector<glm::vec3>& normals, const QVector<float>& strokeWidths);
|
||||
static std::vector<Vertex> updateVertices(const QVector<glm::vec3>& points,
|
||||
const QVector<glm::vec3>& normals,
|
||||
const QVector<float>& strokeWidths,
|
||||
const QVector<glm::vec3>& strokeColors,
|
||||
const bool isUVModeStretch,
|
||||
const float textureAspectRatio);
|
||||
|
||||
Transform _polylineTransform;
|
||||
QVector<glm::vec3> _lastPoints;
|
||||
QVector<glm::vec3> _lastNormals;
|
||||
QVector<glm::vec3> _lastStrokeColors;
|
||||
QVector<float> _lastStrokeWidths;
|
||||
gpu::BufferPointer _verticesBuffer;
|
||||
gpu::BufferView _uniformBuffer;
|
||||
|
||||
uint32_t _numVertices { 0 };
|
||||
bool _empty{ true };
|
||||
NetworkTexturePointer _texture;
|
||||
float _textureAspectRatio { 1.0f };
|
||||
|
||||
};
|
||||
|
||||
} } // namespace
|
||||
|
|
|
@ -40,7 +40,7 @@ void main(void) {
|
|||
packDeferredFragmentTranslucent(
|
||||
float(frontCondition) * interpolatedNormal,
|
||||
texel.a * varColor.a,
|
||||
polyline.color * texel.rgb,
|
||||
color * texel.rgb,
|
||||
vec3(0.01, 0.01, 0.01),
|
||||
10.0);
|
||||
}
|
||||
|
|
|
@ -228,11 +228,21 @@ const std::array<ComponentPair, COMPONENT_MODE_ITEM_COUNT> COMPONENT_MODES = { {
|
|||
} };
|
||||
|
||||
QString EntityItemProperties::getHazeModeAsString() const {
|
||||
return COMPONENT_MODES[_hazeMode].second;
|
||||
// return "inherit" if _hazeMode is not valid
|
||||
if (_hazeMode < COMPONENT_MODE_ITEM_COUNT) {
|
||||
return COMPONENT_MODES[_hazeMode].second;
|
||||
} else {
|
||||
return COMPONENT_MODES[COMPONENT_MODE_INHERIT].second;
|
||||
}
|
||||
}
|
||||
|
||||
QString EntityItemProperties::getHazeModeString(uint32_t mode) {
|
||||
return COMPONENT_MODES[mode].second;
|
||||
// return "inherit" if mode is not valid
|
||||
if (mode < COMPONENT_MODE_ITEM_COUNT) {
|
||||
return COMPONENT_MODES[mode].second;
|
||||
} else {
|
||||
return COMPONENT_MODES[COMPONENT_MODE_INHERIT].second;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityItemProperties::setHazeModeFromString(const QString& hazeMode) {
|
||||
|
@ -345,7 +355,9 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
|||
CHECK_PROPERTY_CHANGE(PROP_FACE_CAMERA, faceCamera);
|
||||
CHECK_PROPERTY_CHANGE(PROP_ACTION_DATA, actionData);
|
||||
CHECK_PROPERTY_CHANGE(PROP_NORMALS, normals);
|
||||
CHECK_PROPERTY_CHANGE(PROP_STROKE_COLORS, strokeColors);
|
||||
CHECK_PROPERTY_CHANGE(PROP_STROKE_WIDTHS, strokeWidths);
|
||||
CHECK_PROPERTY_CHANGE(PROP_IS_UV_MODE_STRETCH, isUVModeStretch);
|
||||
CHECK_PROPERTY_CHANGE(PROP_X_TEXTURE_URL, xTextureURL);
|
||||
CHECK_PROPERTY_CHANGE(PROP_Y_TEXTURE_URL, yTextureURL);
|
||||
CHECK_PROPERTY_CHANGE(PROP_Z_TEXTURE_URL, zTextureURL);
|
||||
|
@ -595,8 +607,10 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
|
|||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LINE_WIDTH, lineWidth);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LINE_POINTS, linePoints);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_NORMALS, normals);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_STROKE_COLORS, strokeColors);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_STROKE_WIDTHS, strokeWidths);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_TEXTURES, textures);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_IS_UV_MODE_STRETCH, isUVModeStretch);
|
||||
}
|
||||
|
||||
if (!skipDefaults && !strictSemantics) {
|
||||
|
@ -761,7 +775,10 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
|
|||
COPY_PROPERTY_FROM_QSCRIPTVALUE(faceCamera, bool, setFaceCamera);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(actionData, QByteArray, setActionData);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(normals, qVectorVec3, setNormals);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(strokeColors, qVectorVec3, setStrokeColors);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(strokeWidths,qVectorFloat, setStrokeWidths);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(isUVModeStretch, bool, setIsUVModeStretch);
|
||||
|
||||
|
||||
if (!honorReadOnly) {
|
||||
// this is used by the json reader to set things that we don't want javascript to able to affect.
|
||||
|
@ -915,7 +932,9 @@ void EntityItemProperties::merge(const EntityItemProperties& other) {
|
|||
COPY_PROPERTY_IF_CHANGED(faceCamera);
|
||||
COPY_PROPERTY_IF_CHANGED(actionData);
|
||||
COPY_PROPERTY_IF_CHANGED(normals);
|
||||
COPY_PROPERTY_IF_CHANGED(strokeColors);
|
||||
COPY_PROPERTY_IF_CHANGED(strokeWidths);
|
||||
COPY_PROPERTY_IF_CHANGED(isUVModeStretch);
|
||||
COPY_PROPERTY_IF_CHANGED(created);
|
||||
|
||||
_animation.merge(other._animation);
|
||||
|
@ -1102,7 +1121,9 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue
|
|||
ADD_PROPERTY_TO_MAP(PROP_FACE_CAMERA, FaceCamera, faceCamera, bool);
|
||||
ADD_PROPERTY_TO_MAP(PROP_ACTION_DATA, ActionData, actionData, QByteArray);
|
||||
ADD_PROPERTY_TO_MAP(PROP_NORMALS, Normals, normals, QVector<glm::vec3>);
|
||||
ADD_PROPERTY_TO_MAP(PROP_STROKE_COLORS, StrokeColors, strokeColors, QVector<glm::vec3>);
|
||||
ADD_PROPERTY_TO_MAP(PROP_STROKE_WIDTHS, StrokeWidths, strokeWidths, QVector<float>);
|
||||
ADD_PROPERTY_TO_MAP(PROP_IS_UV_MODE_STRETCH, IsUVModeStretch, isUVModeStretch, QVector<float>);
|
||||
ADD_PROPERTY_TO_MAP(PROP_X_TEXTURE_URL, XTextureURL, xTextureURL, QString);
|
||||
ADD_PROPERTY_TO_MAP(PROP_Y_TEXTURE_URL, YTextureURL, yTextureURL, QString);
|
||||
ADD_PROPERTY_TO_MAP(PROP_Z_TEXTURE_URL, ZTextureURL, zTextureURL, QString);
|
||||
|
@ -1448,9 +1469,11 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
|
|||
if (properties.getType() == EntityTypes::PolyLine) {
|
||||
APPEND_ENTITY_PROPERTY(PROP_LINE_WIDTH, properties.getLineWidth());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LINE_POINTS, properties.getLinePoints());
|
||||
APPEND_ENTITY_PROPERTY(PROP_NORMALS, properties.getNormals());
|
||||
APPEND_ENTITY_PROPERTY(PROP_NORMALS, properties.getPackedNormals());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STROKE_COLORS, properties.getPackedStrokeColors());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STROKE_WIDTHS, properties.getStrokeWidths());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, properties.getTextures());
|
||||
APPEND_ENTITY_PROPERTY(PROP_IS_UV_MODE_STRETCH, properties.getIsUVModeStretch());
|
||||
}
|
||||
// NOTE: Spheres and Boxes are just special cases of Shape, and they need to include their PROP_SHAPE
|
||||
// when encoding/decoding edits because otherwise they can't polymorph to other shape types
|
||||
|
@ -1537,6 +1560,44 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
|
|||
return success;
|
||||
}
|
||||
|
||||
QByteArray EntityItemProperties::getPackedNormals() const {
|
||||
return packNormals(getNormals());
|
||||
}
|
||||
|
||||
QByteArray EntityItemProperties::packNormals(const QVector<glm::vec3>& normals) const {
|
||||
int normalsSize = normals.size();
|
||||
QByteArray packedNormals = QByteArray(normalsSize * 6 + 1, '0');
|
||||
// add size of the array
|
||||
packedNormals[0] = ((uint8_t)normalsSize);
|
||||
|
||||
int index = 1;
|
||||
for (int i = 0; i < normalsSize; i++) {
|
||||
int numBytes = packFloatVec3ToSignedTwoByteFixed((unsigned char*)packedNormals.data() + index, normals[i], 15);
|
||||
index += numBytes;
|
||||
}
|
||||
return packedNormals;
|
||||
}
|
||||
|
||||
QByteArray EntityItemProperties::getPackedStrokeColors() const {
|
||||
return packStrokeColors(getStrokeColors());
|
||||
}
|
||||
QByteArray EntityItemProperties::packStrokeColors(const QVector<glm::vec3>& strokeColors) const {
|
||||
int strokeColorsSize = strokeColors.size();
|
||||
QByteArray packedStrokeColors = QByteArray(strokeColorsSize * 3 + 1, '0');
|
||||
|
||||
// add size of the array
|
||||
packedStrokeColors[0] = ((uint8_t)strokeColorsSize);
|
||||
|
||||
|
||||
for (int i = 0; i < strokeColorsSize; i++) {
|
||||
// add the color to the QByteArray
|
||||
packedStrokeColors[i * 3 + 1] = strokeColors[i].r * 255;
|
||||
packedStrokeColors[i * 3 + 2] = strokeColors[i].g * 255;
|
||||
packedStrokeColors[i * 3 + 3] = strokeColors[i].b * 255;
|
||||
}
|
||||
return packedStrokeColors;
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// how to handle lastEdited?
|
||||
// how to handle lastUpdated?
|
||||
|
@ -1758,9 +1819,11 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
if (properties.getType() == EntityTypes::PolyLine) {
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LINE_WIDTH, float, setLineWidth);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LINE_POINTS, QVector<glm::vec3>, setLinePoints);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_NORMALS, QVector<glm::vec3>, setNormals);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_NORMALS, QByteArray, setPackedNormals);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_STROKE_COLORS, QByteArray, setPackedStrokeColors);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_STROKE_WIDTHS, QVector<float>, setStrokeWidths);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXTURES, QString, setTextures);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_IS_UV_MODE_STRETCH, bool, setIsUVModeStretch);
|
||||
}
|
||||
|
||||
// NOTE: Spheres and Boxes are just special cases of Shape, and they need to include their PROP_SHAPE
|
||||
|
@ -1791,6 +1854,53 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
return valid;
|
||||
}
|
||||
|
||||
void EntityItemProperties::setPackedNormals(const QByteArray& value) {
|
||||
setNormals(unpackNormals(value));
|
||||
}
|
||||
|
||||
QVector<glm::vec3> EntityItemProperties::unpackNormals(const QByteArray& normals) {
|
||||
// the size of the vector is packed first
|
||||
QVector<glm::vec3> unpackedNormals = QVector<glm::vec3>((int)normals[0]);
|
||||
|
||||
if ((int)normals[0] == normals.size() / 6) {
|
||||
int j = 0;
|
||||
for (int i = 1; i < normals.size();) {
|
||||
glm::vec3 aux = glm::vec3();
|
||||
i += unpackFloatVec3FromSignedTwoByteFixed((unsigned char*)normals.data() + i, aux, 15);
|
||||
unpackedNormals[j] = aux;
|
||||
j++;
|
||||
}
|
||||
} else {
|
||||
qCDebug(entities) << "WARNING - Expected received size for normals does not match. Expected: " << (int)normals[0]
|
||||
<< " Received: " << (normals.size() / 6);
|
||||
}
|
||||
return unpackedNormals;
|
||||
}
|
||||
|
||||
void EntityItemProperties::setPackedStrokeColors(const QByteArray& value) {
|
||||
setStrokeColors(unpackStrokeColors(value));
|
||||
}
|
||||
|
||||
QVector<glm::vec3> EntityItemProperties::unpackStrokeColors(const QByteArray& strokeColors) {
|
||||
// the size of the vector is packed first
|
||||
QVector<glm::vec3> unpackedStrokeColors = QVector<glm::vec3>((int)strokeColors[0]);
|
||||
|
||||
if ((int)strokeColors[0] == strokeColors.size() / 3) {
|
||||
int j = 0;
|
||||
for (int i = 1; i < strokeColors.size();) {
|
||||
|
||||
float r = (uint8_t)strokeColors[i++] / 255.0f;
|
||||
float g = (uint8_t)strokeColors[i++] / 255.0f;
|
||||
float b = (uint8_t)strokeColors[i++] / 255.0f;
|
||||
unpackedStrokeColors[j++] = glmVec3(r, g, b);
|
||||
}
|
||||
} else {
|
||||
qCDebug(entities) << "WARNING - Expected received size for stroke colors does not match. Expected: "
|
||||
<< (int)strokeColors[0] << " Received: " << (strokeColors.size() / 3);
|
||||
}
|
||||
|
||||
return unpackedStrokeColors;
|
||||
}
|
||||
|
||||
// NOTE: This version will only encode the portion of the edit message immediately following the
|
||||
// header it does not include the send times and sequence number because that is handled by the
|
||||
|
@ -1932,7 +2042,9 @@ void EntityItemProperties::markAllChanged() {
|
|||
_actionDataChanged = true;
|
||||
|
||||
_normalsChanged = true;
|
||||
_strokeColorsChanged = true;
|
||||
_strokeWidthsChanged = true;
|
||||
_isUVModeStretchChanged = true;
|
||||
|
||||
_xTextureURLChanged = true;
|
||||
_yTextureURLChanged = true;
|
||||
|
@ -2347,6 +2459,14 @@ QList<QString> EntityItemProperties::listChangedProperties() {
|
|||
out += "shape";
|
||||
}
|
||||
|
||||
if (strokeColorsChanged()) {
|
||||
out += "strokeColors";
|
||||
}
|
||||
|
||||
if (isUVModeStretchChanged()) {
|
||||
out += "isUVModeStretch";
|
||||
}
|
||||
|
||||
getAnimation().listChangedProperties(out);
|
||||
getKeyLight().listChangedProperties(out);
|
||||
getSkybox().listChangedProperties(out);
|
||||
|
|
|
@ -191,8 +191,10 @@ public:
|
|||
DEFINE_PROPERTY_REF(PROP_DESCRIPTION, Description, description, QString, "");
|
||||
DEFINE_PROPERTY(PROP_FACE_CAMERA, FaceCamera, faceCamera, bool, TextEntityItem::DEFAULT_FACE_CAMERA);
|
||||
DEFINE_PROPERTY_REF(PROP_ACTION_DATA, ActionData, actionData, QByteArray, QByteArray());
|
||||
DEFINE_PROPERTY(PROP_NORMALS, Normals, normals, QVector<glm::vec3>, QVector<glm::vec3>());
|
||||
DEFINE_PROPERTY(PROP_NORMALS, Normals, normals, QVector<glm::vec3>, ENTITY_ITEM_DEFAULT_EMPTY_VEC3_QVEC);
|
||||
DEFINE_PROPERTY(PROP_STROKE_COLORS, StrokeColors, strokeColors, QVector<glm::vec3>, ENTITY_ITEM_DEFAULT_EMPTY_VEC3_QVEC);
|
||||
DEFINE_PROPERTY(PROP_STROKE_WIDTHS, StrokeWidths, strokeWidths, QVector<float>, QVector<float>());
|
||||
DEFINE_PROPERTY(PROP_IS_UV_MODE_STRETCH, IsUVModeStretch, isUVModeStretch, bool, true);
|
||||
DEFINE_PROPERTY_REF(PROP_X_TEXTURE_URL, XTextureURL, xTextureURL, QString, "");
|
||||
DEFINE_PROPERTY_REF(PROP_Y_TEXTURE_URL, YTextureURL, yTextureURL, QString, "");
|
||||
DEFINE_PROPERTY_REF(PROP_Z_TEXTURE_URL, ZTextureURL, zTextureURL, QString, "");
|
||||
|
@ -322,6 +324,17 @@ public:
|
|||
bool getRenderInfoHasTransparent() const { return _renderInfoHasTransparent; }
|
||||
void setRenderInfoHasTransparent(bool value) { _renderInfoHasTransparent = value; }
|
||||
|
||||
void setPackedNormals(const QByteArray& value);
|
||||
QVector<glm::vec3> unpackNormals(const QByteArray& normals);
|
||||
|
||||
void setPackedStrokeColors(const QByteArray& value);
|
||||
QVector<glm::vec3> unpackStrokeColors(const QByteArray& strokeColors);
|
||||
|
||||
QByteArray getPackedNormals() const;
|
||||
QByteArray packNormals(const QVector<glm::vec3>& normals) const;
|
||||
|
||||
QByteArray getPackedStrokeColors() const;
|
||||
QByteArray packStrokeColors(const QVector<glm::vec3>& strokeColors) const;
|
||||
|
||||
protected:
|
||||
QString getCollisionMaskAsString() const;
|
||||
|
|
|
@ -24,6 +24,8 @@ const glm::vec3 ENTITY_ITEM_ZERO_VEC3 = glm::vec3(0.0f);
|
|||
const glm::vec3 ENTITY_ITEM_ONE_VEC3 = glm::vec3(1.0f);
|
||||
const glm::vec3 ENTITY_ITEM_HALF_VEC3 = glm::vec3(0.5f);
|
||||
|
||||
const QVector<glm::vec3> ENTITY_ITEM_DEFAULT_EMPTY_VEC3_QVEC = QVector<glm::vec3>();
|
||||
|
||||
const bool ENTITY_ITEM_DEFAULT_LOCKED = false;
|
||||
const QString ENTITY_ITEM_DEFAULT_USER_DATA = QString("");
|
||||
const QUuid ENTITY_ITEM_DEFAULT_SIMULATOR_ID = QUuid();
|
||||
|
|
|
@ -109,7 +109,9 @@ enum EntityPropertyList {
|
|||
|
||||
// Used by PolyLine entity
|
||||
PROP_NORMALS,
|
||||
PROP_STROKE_COLORS,
|
||||
PROP_STROKE_WIDTHS,
|
||||
PROP_IS_UV_MODE_STRETCH,
|
||||
|
||||
// used by particles
|
||||
PROP_SPEED_SPREAD,
|
||||
|
|
|
@ -9,9 +9,11 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <AACube.h>
|
||||
|
||||
#include "EntitySimulation.h"
|
||||
|
||||
#include <AACube.h>
|
||||
#include <Profile.h>
|
||||
|
||||
#include "EntitiesLogging.h"
|
||||
#include "MovingEntitiesOperator.h"
|
||||
|
||||
|
@ -27,6 +29,7 @@ void EntitySimulation::setEntityTree(EntityTreePointer tree) {
|
|||
}
|
||||
|
||||
void EntitySimulation::updateEntities() {
|
||||
PROFILE_RANGE(simulation_physics, "ES::updateEntities");
|
||||
QMutexLocker lock(&_mutex);
|
||||
quint64 now = usecTimestampNow();
|
||||
|
||||
|
@ -35,8 +38,12 @@ void EntitySimulation::updateEntities() {
|
|||
callUpdateOnEntitiesThatNeedIt(now);
|
||||
moveSimpleKinematics(now);
|
||||
updateEntitiesInternal(now);
|
||||
PerformanceTimer perfTimer("sortingEntities");
|
||||
sortEntitiesThatMoved();
|
||||
|
||||
{
|
||||
PROFILE_RANGE(simulation_physics, "Sort");
|
||||
PerformanceTimer perfTimer("sortingEntities");
|
||||
sortEntitiesThatMoved();
|
||||
}
|
||||
}
|
||||
|
||||
void EntitySimulation::takeEntitiesToDelete(VectorOfEntities& entitiesToDelete) {
|
||||
|
@ -258,6 +265,7 @@ void EntitySimulation::clearEntities() {
|
|||
}
|
||||
|
||||
void EntitySimulation::moveSimpleKinematics(const quint64& now) {
|
||||
PROFILE_RANGE_EX(simulation_physics, "Kinematics", 0xffff00ff, (uint64_t)_simpleKinematicEntities.size());
|
||||
SetOfEntities::iterator itemItr = _simpleKinematicEntities.begin();
|
||||
while (itemItr != _simpleKinematicEntities.end()) {
|
||||
EntityItemPointer entity = *itemItr;
|
||||
|
|
|
@ -15,8 +15,9 @@
|
|||
|
||||
#include <QtScript/QScriptEngine>
|
||||
|
||||
#include <PerfStat.h>
|
||||
#include <Extents.h>
|
||||
#include <PerfStat.h>
|
||||
#include <Profile.h>
|
||||
|
||||
#include "EntitySimulation.h"
|
||||
#include "VariantMapToScriptValue.h"
|
||||
|
@ -1370,6 +1371,7 @@ void EntityTree::entityChanged(EntityItemPointer entity) {
|
|||
|
||||
|
||||
void EntityTree::fixupNeedsParentFixups() {
|
||||
PROFILE_RANGE(simulation_physics, "FixupParents");
|
||||
MovingEntitiesOperator moveOperator;
|
||||
|
||||
QWriteLocker locker(&_needsParentFixupLock);
|
||||
|
@ -1459,6 +1461,7 @@ void EntityTree::addToNeedsParentFixupList(EntityItemPointer entity) {
|
|||
}
|
||||
|
||||
void EntityTree::update(bool simulate) {
|
||||
PROFILE_RANGE(simulation_physics, "ET::update");
|
||||
fixupNeedsParentFixups();
|
||||
if (simulate && _simulation) {
|
||||
withWriteLock([&] {
|
||||
|
|
|
@ -557,12 +557,6 @@ void ModelEntityItem::setAnimationLoop(bool loop) {
|
|||
});
|
||||
}
|
||||
|
||||
bool ModelEntityItem::getAnimationLoop() const {
|
||||
return resultWithReadLock<bool>([&] {
|
||||
return _animationProperties.getLoop();
|
||||
});
|
||||
}
|
||||
|
||||
void ModelEntityItem::setAnimationHold(bool hold) {
|
||||
withWriteLock([&] {
|
||||
_animationProperties.setHold(hold);
|
||||
|
@ -610,8 +604,10 @@ float ModelEntityItem::getAnimationCurrentFrame() const {
|
|||
});
|
||||
}
|
||||
|
||||
float ModelEntityItem::getAnimationFPS() const {
|
||||
bool ModelEntityItem::isAnimatingSomething() const {
|
||||
return resultWithReadLock<float>([&] {
|
||||
return _animationProperties.getFPS();
|
||||
});
|
||||
return !_animationProperties.getURL().isEmpty() &&
|
||||
_animationProperties.getRunning() &&
|
||||
(_animationProperties.getFPS() != 0.0f);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -90,7 +90,6 @@ public:
|
|||
bool getAnimationAllowTranslation() const { return _animationProperties.getAllowTranslation(); };
|
||||
|
||||
void setAnimationLoop(bool loop);
|
||||
bool getAnimationLoop() const;
|
||||
|
||||
void setAnimationHold(bool hold);
|
||||
bool getAnimationHold() const;
|
||||
|
@ -101,10 +100,9 @@ public:
|
|||
void setAnimationLastFrame(float lastFrame);
|
||||
float getAnimationLastFrame() const;
|
||||
|
||||
|
||||
bool getAnimationIsPlaying() const;
|
||||
float getAnimationCurrentFrame() const;
|
||||
float getAnimationFPS() const;
|
||||
bool isAnimatingSomething() const;
|
||||
|
||||
static const QString DEFAULT_TEXTURES;
|
||||
const QString getTextures() const;
|
||||
|
@ -123,7 +121,6 @@ public:
|
|||
QVector<bool> getJointRotationsSet() const;
|
||||
QVector<glm::vec3> getJointTranslations() const;
|
||||
QVector<bool> getJointTranslationsSet() const;
|
||||
bool isAnimatingSomething() const;
|
||||
|
||||
private:
|
||||
void setAnimationSettings(const QString& value); // only called for old bitstream format
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "PolyLineEntityItem.h"
|
||||
|
||||
const float PolyLineEntityItem::DEFAULT_LINE_WIDTH = 0.1f;
|
||||
const int PolyLineEntityItem::MAX_POINTS_PER_LINE = 70;
|
||||
const int PolyLineEntityItem::MAX_POINTS_PER_LINE = 60;
|
||||
|
||||
|
||||
EntityItemPointer PolyLineEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
|
@ -31,6 +31,7 @@ EntityItemPointer PolyLineEntityItem::factory(const EntityItemID& entityID, cons
|
|||
return entity;
|
||||
}
|
||||
|
||||
|
||||
PolyLineEntityItem::PolyLineEntityItem(const EntityItemID& entityItemID) : EntityItem(entityItemID) {
|
||||
_type = EntityTypes::PolyLine;
|
||||
}
|
||||
|
@ -42,12 +43,15 @@ EntityItemProperties PolyLineEntityItem::getProperties(EntityPropertyFlags desir
|
|||
|
||||
properties._color = getXColor();
|
||||
properties._colorChanged = false;
|
||||
|
||||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(lineWidth, getLineWidth);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(linePoints, getLinePoints);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(normals, getNormals);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(strokeColors, getStrokeColors);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(strokeWidths, getStrokeWidths);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(textures, getTextures);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(isUVModeStretch, getIsUVModeStretch);
|
||||
return properties;
|
||||
}
|
||||
|
||||
|
@ -60,8 +64,10 @@ bool PolyLineEntityItem::setProperties(const EntityItemProperties& properties) {
|
|||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(lineWidth, setLineWidth);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(linePoints, setLinePoints);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(normals, setNormals);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(strokeColors, setStrokeColors);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(strokeWidths, setStrokeWidths);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(textures, setTextures);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(isUVModeStretch, setIsUVModeStretch);
|
||||
|
||||
if (somethingChanged) {
|
||||
bool wantDebug = false;
|
||||
|
@ -108,6 +114,15 @@ bool PolyLineEntityItem::setNormals(const QVector<glm::vec3>& normals) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool PolyLineEntityItem::setStrokeColors(const QVector<glm::vec3>& strokeColors) {
|
||||
withWriteLock([&] {
|
||||
_strokeColors = strokeColors;
|
||||
_strokeColorsChanged = true;
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool PolyLineEntityItem::setLinePoints(const QVector<glm::vec3>& points) {
|
||||
if (points.size() > MAX_POINTS_PER_LINE) {
|
||||
return false;
|
||||
|
@ -193,8 +208,10 @@ int PolyLineEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* da
|
|||
READ_ENTITY_PROPERTY(PROP_LINE_WIDTH, float, setLineWidth);
|
||||
READ_ENTITY_PROPERTY(PROP_LINE_POINTS, QVector<glm::vec3>, setLinePoints);
|
||||
READ_ENTITY_PROPERTY(PROP_NORMALS, QVector<glm::vec3>, setNormals);
|
||||
READ_ENTITY_PROPERTY(PROP_STROKE_COLORS, QVector<glm::vec3>, setStrokeColors);
|
||||
READ_ENTITY_PROPERTY(PROP_STROKE_WIDTHS, QVector<float>, setStrokeWidths);
|
||||
READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures);
|
||||
READ_ENTITY_PROPERTY(PROP_IS_UV_MODE_STRETCH, bool, setIsUVModeStretch);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
@ -207,8 +224,10 @@ EntityPropertyFlags PolyLineEntityItem::getEntityProperties(EncodeBitstreamParam
|
|||
requestedProperties += PROP_LINE_WIDTH;
|
||||
requestedProperties += PROP_LINE_POINTS;
|
||||
requestedProperties += PROP_NORMALS;
|
||||
requestedProperties += PROP_STROKE_COLORS;
|
||||
requestedProperties += PROP_STROKE_WIDTHS;
|
||||
requestedProperties += PROP_TEXTURES;
|
||||
requestedProperties += PROP_IS_UV_MODE_STRETCH;
|
||||
return requestedProperties;
|
||||
}
|
||||
|
||||
|
@ -227,8 +246,10 @@ void PolyLineEntityItem::appendSubclassData(OctreePacketData* packetData, Encode
|
|||
APPEND_ENTITY_PROPERTY(PROP_LINE_WIDTH, getLineWidth());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LINE_POINTS, getLinePoints());
|
||||
APPEND_ENTITY_PROPERTY(PROP_NORMALS, getNormals());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STROKE_COLORS, getStrokeColors());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STROKE_WIDTHS, getStrokeWidths());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, getTextures());
|
||||
APPEND_ENTITY_PROPERTY(PROP_IS_UV_MODE_STRETCH, getIsUVModeStretch());
|
||||
}
|
||||
|
||||
void PolyLineEntityItem::debugDump() const {
|
||||
|
@ -258,6 +279,14 @@ QVector<glm::vec3> PolyLineEntityItem::getNormals() const {
|
|||
return result;
|
||||
}
|
||||
|
||||
QVector<glm::vec3> PolyLineEntityItem::getStrokeColors() const {
|
||||
QVector<glm::vec3> result;
|
||||
withReadLock([&] {
|
||||
result = _strokeColors;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
QVector<float> PolyLineEntityItem::getStrokeWidths() const {
|
||||
QVector<float> result;
|
||||
withReadLock([&] {
|
||||
|
|
|
@ -46,9 +46,11 @@ class PolyLineEntityItem : public EntityItem {
|
|||
xColor getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; }
|
||||
|
||||
void setColor(const rgbColor& value) {
|
||||
_strokeColorsChanged = true;
|
||||
memcpy(_color, value, sizeof(_color));
|
||||
}
|
||||
void setColor(const xColor& value) {
|
||||
_strokeColorsChanged = true;
|
||||
_color[RED_INDEX] = value.red;
|
||||
_color[GREEN_INDEX] = value.green;
|
||||
_color[BLUE_INDEX] = value.blue;
|
||||
|
@ -64,9 +66,15 @@ class PolyLineEntityItem : public EntityItem {
|
|||
bool setNormals(const QVector<glm::vec3>& normals);
|
||||
QVector<glm::vec3> getNormals() const;
|
||||
|
||||
bool setStrokeColors(const QVector<glm::vec3>& strokeColors);
|
||||
QVector<glm::vec3> getStrokeColors() const;
|
||||
|
||||
bool setStrokeWidths(const QVector<float>& strokeWidths);
|
||||
QVector<float> getStrokeWidths() const;
|
||||
|
||||
void setIsUVModeStretch(bool isUVModeStretch){ _isUVModeStretch = isUVModeStretch; }
|
||||
bool getIsUVModeStretch() const{ return _isUVModeStretch; }
|
||||
|
||||
QString getTextures() const;
|
||||
void setTextures(const QString& textures);
|
||||
|
||||
|
@ -76,10 +84,11 @@ class PolyLineEntityItem : public EntityItem {
|
|||
|
||||
bool pointsChanged() const { return _pointsChanged; }
|
||||
bool normalsChanged() const { return _normalsChanged; }
|
||||
bool strokeColorsChanged() const { return _strokeColorsChanged; }
|
||||
bool strokeWidthsChanged() const { return _strokeWidthsChanged; }
|
||||
bool texturesChanged() const { return _texturesChangedFlag; }
|
||||
void resetTexturesChanged() { _texturesChangedFlag = false; }
|
||||
void resetPolyLineChanged() { _strokeWidthsChanged = _normalsChanged = _pointsChanged = false; }
|
||||
void resetPolyLineChanged() { _strokeColorsChanged = _strokeWidthsChanged = _normalsChanged = _pointsChanged = false; }
|
||||
|
||||
|
||||
// never have a ray intersection pick a PolyLineEntityItem.
|
||||
|
@ -103,11 +112,14 @@ private:
|
|||
float _lineWidth { DEFAULT_LINE_WIDTH };
|
||||
bool _pointsChanged { true };
|
||||
bool _normalsChanged { true };
|
||||
bool _strokeColorsChanged { true };
|
||||
bool _strokeWidthsChanged { true };
|
||||
QVector<glm::vec3> _points;
|
||||
QVector<glm::vec3> _normals;
|
||||
QVector<glm::vec3> _strokeColors;
|
||||
QVector<float> _strokeWidths;
|
||||
QString _textures;
|
||||
bool _isUVModeStretch;
|
||||
bool _texturesChangedFlag { false };
|
||||
mutable QReadWriteLock _quadReadWriteLock;
|
||||
};
|
||||
|
|
|
@ -321,8 +321,10 @@ void ZoneEntityItem::resetRenderingPropertiesChanged() {
|
|||
}
|
||||
|
||||
void ZoneEntityItem::setHazeMode(const uint32_t value) {
|
||||
_hazeMode = value;
|
||||
_hazePropertiesChanged = true;
|
||||
if (value < COMPONENT_MODE_ITEM_COUNT) {
|
||||
_hazeMode = value;
|
||||
_hazePropertiesChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t ZoneEntityItem::getHazeMode() const {
|
||||
|
|
|
@ -138,6 +138,8 @@ public:
|
|||
static const bool DEFAULT_GHOSTING_ALLOWED;
|
||||
static const QString DEFAULT_FILTER_URL;
|
||||
|
||||
static const uint32_t DEFAULT_HAZE_MODE{ (uint32_t)COMPONENT_MODE_INHERIT };
|
||||
|
||||
protected:
|
||||
KeyLightPropertyGroup _keyLightProperties;
|
||||
|
||||
|
@ -146,7 +148,7 @@ protected:
|
|||
|
||||
BackgroundMode _backgroundMode = BACKGROUND_MODE_INHERIT;
|
||||
|
||||
uint8_t _hazeMode{ (uint8_t)COMPONENT_MODE_INHERIT };
|
||||
uint32_t _hazeMode{ DEFAULT_HAZE_MODE };
|
||||
|
||||
float _hazeRange{ HazePropertyGroup::DEFAULT_HAZE_RANGE };
|
||||
xColor _hazeColor{ HazePropertyGroup::DEFAULT_HAZE_COLOR };
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <glm/gtx/transform.hpp>
|
||||
#include <math.h>
|
||||
#include <qcompilerdetection.h>
|
||||
#include <ComponentMode.h>
|
||||
|
||||
using namespace model;
|
||||
|
||||
|
@ -256,8 +257,9 @@ void SunSkyStage::setSkybox(const SkyboxPointer& skybox) {
|
|||
invalidate();
|
||||
}
|
||||
|
||||
// Haze
|
||||
void SunSkyStage::setHazeMode(uint32_t mode) {
|
||||
_hazeMode = mode;
|
||||
invalidate();
|
||||
void SunSkyStage::setHazeMode(uint32_t hazeMode) {
|
||||
if (hazeMode < COMPONENT_MODE_ITEM_COUNT) {
|
||||
_hazeMode = hazeMode;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
|||
case PacketType::EntityAdd:
|
||||
case PacketType::EntityEdit:
|
||||
case PacketType::EntityData:
|
||||
return VERSION_ENTITIES_STROKE_COLOR_PROPERTY;
|
||||
case PacketType::EntityPhysics:
|
||||
return VERSION_ENTITIES_HAZE;
|
||||
case PacketType::EntityQuery:
|
||||
|
|
|
@ -269,6 +269,9 @@ 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;
|
||||
|
||||
|
||||
enum class EntityQueryPacketVersion: PacketVersion {
|
||||
JSONFilter = 18,
|
||||
|
|
5
libraries/pointers/CMakeLists.txt
Normal file
5
libraries/pointers/CMakeLists.txt
Normal file
|
@ -0,0 +1,5 @@
|
|||
set(TARGET_NAME pointers)
|
||||
setup_hifi_library()
|
||||
GroupSources(src)
|
||||
link_hifi_libraries(shared)
|
||||
|
6
libraries/pointers/src/pointers/PointerManager.cpp
Normal file
6
libraries/pointers/src/pointers/PointerManager.cpp
Normal file
|
@ -0,0 +1,6 @@
|
|||
#include "PointerManager.h"
|
||||
|
||||
PointerManager::PointerManager() {
|
||||
|
||||
}
|
||||
|
30
libraries/pointers/src/pointers/PointerManager.h
Normal file
30
libraries/pointers/src/pointers/PointerManager.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis on 2017/10/16
|
||||
// Copyright 2013-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
|
||||
//
|
||||
#ifndef hifi_pointers_PointerManager_h
|
||||
#define hifi_pointers_PointerManager_h
|
||||
|
||||
#include <DependencyManager.h>
|
||||
#include <PointerEvent.h>
|
||||
|
||||
class PointerManager : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
SINGLETON_DEPENDENCY
|
||||
public:
|
||||
PointerManager();
|
||||
|
||||
signals:
|
||||
void triggerBegin(const QUuid& id, const PointerEvent& pointerEvent);
|
||||
void triggerContinue(const QUuid& id, const PointerEvent& pointerEvent);
|
||||
void triggerEnd(const QUuid& id, const PointerEvent& pointerEvent);
|
||||
|
||||
void hoverEnter(const QUuid& id, const PointerEvent& pointerEvent);
|
||||
void hoverOver(const QUuid& id, const PointerEvent& pointerEvent);
|
||||
void hoverLeave(const QUuid& id, const PointerEvent& pointerEvent);
|
||||
};
|
||||
|
||||
#endif // hifi_pointers_PointerManager_h
|
81
libraries/pointers/src/pointers/rays/RayPick.cpp
Normal file
81
libraries/pointers/src/pointers/rays/RayPick.cpp
Normal file
|
@ -0,0 +1,81 @@
|
|||
//
|
||||
// Created by Sam Gondelman 7/11/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
|
||||
//
|
||||
#include "RayPick.h"
|
||||
|
||||
const RayPickFilter RayPickFilter::NOTHING;
|
||||
|
||||
RayPick::RayPick(const RayPickFilter& filter, const float maxDistance, const bool enabled) :
|
||||
_filter(filter),
|
||||
_maxDistance(maxDistance),
|
||||
_enabled(enabled)
|
||||
{
|
||||
}
|
||||
|
||||
void RayPick::enable(bool enabled) {
|
||||
withWriteLock([&] {
|
||||
_enabled = enabled;
|
||||
});
|
||||
}
|
||||
|
||||
RayPickFilter RayPick::getFilter() const {
|
||||
return resultWithReadLock<RayPickFilter>([&] {
|
||||
return _filter;
|
||||
});
|
||||
}
|
||||
|
||||
float RayPick::getMaxDistance() const {
|
||||
return _maxDistance;
|
||||
}
|
||||
|
||||
bool RayPick::isEnabled() const {
|
||||
return resultWithReadLock<bool>([&] {
|
||||
return _enabled;
|
||||
});
|
||||
}
|
||||
|
||||
void RayPick::setPrecisionPicking(bool precisionPicking) {
|
||||
withWriteLock([&]{
|
||||
_filter.setFlag(RayPickFilter::PICK_COARSE, !precisionPicking);
|
||||
});
|
||||
}
|
||||
|
||||
void RayPick::setRayPickResult(const RayPickResult& rayPickResult) {
|
||||
withWriteLock([&] {
|
||||
_prevResult = rayPickResult;
|
||||
});
|
||||
}
|
||||
|
||||
QVector<QUuid> RayPick::getIgnoreItems() const {
|
||||
return resultWithReadLock<QVector<QUuid>>([&] {
|
||||
return _ignoreItems;
|
||||
});
|
||||
}
|
||||
|
||||
QVector<QUuid> RayPick::getIncludeItems() const {
|
||||
return resultWithReadLock<QVector<QUuid>>([&] {
|
||||
return _includeItems;
|
||||
});
|
||||
}
|
||||
|
||||
RayPickResult RayPick::getPrevRayPickResult() const {
|
||||
return resultWithReadLock<RayPickResult>([&] {
|
||||
return _prevResult;
|
||||
});
|
||||
}
|
||||
|
||||
void RayPick::setIgnoreItems(const QVector<QUuid>& ignoreItems) {
|
||||
withWriteLock([&] {
|
||||
_ignoreItems = ignoreItems;
|
||||
});
|
||||
}
|
||||
|
||||
void RayPick::setIncludeItems(const QVector<QUuid>& includeItems) {
|
||||
withWriteLock([&] {
|
||||
_includeItems = includeItems;
|
||||
});
|
||||
}
|
|
@ -1,7 +1,4 @@
|
|||
//
|
||||
// RayPick.h
|
||||
// interface/src/raypick
|
||||
//
|
||||
// Created by Sam Gondelman 7/11/2017
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
|
@ -12,22 +9,22 @@
|
|||
#define hifi_RayPick_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include "RegisteredMetaTypes.h"
|
||||
#include <bitset>
|
||||
|
||||
#include "EntityItemID.h"
|
||||
#include "ui/overlays/Overlay.h"
|
||||
#include <QReadWriteLock>
|
||||
#include <QtCore/QUuid>
|
||||
|
||||
#include <RegisteredMetaTypes.h>
|
||||
#include <shared/ReadWriteLockable.h>
|
||||
|
||||
class RayPickFilter {
|
||||
public:
|
||||
enum FlagBit {
|
||||
PICK_NOTHING = 0,
|
||||
PICK_ENTITIES,
|
||||
PICK_ENTITIES = 0,
|
||||
PICK_OVERLAYS,
|
||||
PICK_AVATARS,
|
||||
PICK_HUD,
|
||||
|
||||
PICK_COURSE, // if not set, does precise intersection, otherwise, doesn't
|
||||
PICK_COARSE, // if not set, does precise intersection, otherwise, doesn't
|
||||
|
||||
PICK_INCLUDE_INVISIBLE, // if not set, will not intersect invisible elements, otherwise, intersects both visible and invisible elements
|
||||
PICK_INCLUDE_NONCOLLIDABLE, // if not set, will not intersect noncollidable elements, otherwise, intersects both collidable and noncollidable elements
|
||||
|
@ -42,7 +39,7 @@ public:
|
|||
// The key is the Flags
|
||||
Flags _flags;
|
||||
|
||||
RayPickFilter() : _flags(getBitMask(PICK_NOTHING)) {}
|
||||
RayPickFilter() {}
|
||||
RayPickFilter(const Flags& flags) : _flags(flags) {}
|
||||
|
||||
bool operator== (const RayPickFilter& rhs) const { return _flags == rhs._flags; }
|
||||
|
@ -50,13 +47,13 @@ public:
|
|||
|
||||
void setFlag(FlagBit flag, bool value) { _flags[flag] = value; }
|
||||
|
||||
bool doesPickNothing() const { return _flags[PICK_NOTHING]; }
|
||||
bool doesPickNothing() const { return _flags == NOTHING._flags; }
|
||||
bool doesPickEntities() const { return _flags[PICK_ENTITIES]; }
|
||||
bool doesPickOverlays() const { return _flags[PICK_OVERLAYS]; }
|
||||
bool doesPickAvatars() const { return _flags[PICK_AVATARS]; }
|
||||
bool doesPickHUD() const { return _flags[PICK_HUD]; }
|
||||
|
||||
bool doesPickCourse() const { return _flags[PICK_COURSE]; }
|
||||
bool doesPickCoarse() const { return _flags[PICK_COARSE]; }
|
||||
bool doesPickInvisible() const { return _flags[PICK_INCLUDE_INVISIBLE]; }
|
||||
bool doesPickNonCollidable() const { return _flags[PICK_INCLUDE_NONCOLLIDABLE]; }
|
||||
|
||||
|
@ -71,8 +68,8 @@ public:
|
|||
if (doesPickNonCollidable()) {
|
||||
toReturn |= getBitMask(PICK_INCLUDE_NONCOLLIDABLE);
|
||||
}
|
||||
if (doesPickCourse()) {
|
||||
toReturn |= getBitMask(PICK_COURSE);
|
||||
if (doesPickCoarse()) {
|
||||
toReturn |= getBitMask(PICK_COARSE);
|
||||
}
|
||||
return Flags(toReturn);
|
||||
}
|
||||
|
@ -84,66 +81,76 @@ public:
|
|||
if (doesPickNonCollidable()) {
|
||||
toReturn |= getBitMask(PICK_INCLUDE_NONCOLLIDABLE);
|
||||
}
|
||||
if (doesPickCourse()) {
|
||||
toReturn |= getBitMask(PICK_COURSE);
|
||||
if (doesPickCoarse()) {
|
||||
toReturn |= getBitMask(PICK_COARSE);
|
||||
}
|
||||
return Flags(toReturn);
|
||||
}
|
||||
Flags getAvatarFlags() const { return Flags(getBitMask(PICK_AVATARS)); }
|
||||
Flags getHUDFlags() const { return Flags(getBitMask(PICK_HUD)); }
|
||||
|
||||
static unsigned int getBitMask(FlagBit bit) { return 1 << bit; }
|
||||
static constexpr unsigned int getBitMask(FlagBit bit) { return 1 << bit; }
|
||||
|
||||
static const RayPickFilter NOTHING;
|
||||
};
|
||||
|
||||
class RayPick {
|
||||
class RayPick : protected ReadWriteLockable {
|
||||
|
||||
public:
|
||||
using Pointer = std::shared_ptr<RayPick>;
|
||||
|
||||
RayPick(const RayPickFilter& filter, const float maxDistance, const bool enabled);
|
||||
|
||||
virtual const PickRay getPickRay(bool& valid) const = 0;
|
||||
|
||||
void enable();
|
||||
void disable();
|
||||
void enable(bool enabled = true);
|
||||
void disable() { enable(false); }
|
||||
|
||||
const RayPickFilter& getFilter() { return _filter; }
|
||||
float getMaxDistance() { return _maxDistance; }
|
||||
bool isEnabled() { return _enabled; }
|
||||
const RayPickResult& getPrevRayPickResult();
|
||||
RayPickFilter getFilter() const;
|
||||
float getMaxDistance() const;
|
||||
bool isEnabled() const;
|
||||
RayPickResult getPrevRayPickResult() const;
|
||||
|
||||
void setPrecisionPicking(bool precisionPicking) { _filter.setFlag(RayPickFilter::PICK_COURSE, !precisionPicking); }
|
||||
void setPrecisionPicking(bool precisionPicking);
|
||||
|
||||
void setRayPickResult(const RayPickResult& rayPickResult) { _prevResult = rayPickResult; }
|
||||
void setRayPickResult(const RayPickResult& rayPickResult);
|
||||
|
||||
const QVector<EntityItemID>& getIgnoreEntites() { return _ignoreEntities; }
|
||||
const QVector<EntityItemID>& getIncludeEntites() { return _includeEntities; }
|
||||
const QVector<OverlayID>& getIgnoreOverlays() { return _ignoreOverlays; }
|
||||
const QVector<OverlayID>& getIncludeOverlays() { return _includeOverlays; }
|
||||
const QVector<EntityItemID>& getIgnoreAvatars() { return _ignoreAvatars; }
|
||||
const QVector<EntityItemID>& getIncludeAvatars() { return _includeAvatars; }
|
||||
void setIgnoreEntities(const QScriptValue& ignoreEntities);
|
||||
void setIncludeEntities(const QScriptValue& includeEntities);
|
||||
void setIgnoreOverlays(const QScriptValue& ignoreOverlays);
|
||||
void setIncludeOverlays(const QScriptValue& includeOverlays);
|
||||
void setIgnoreAvatars(const QScriptValue& ignoreAvatars);
|
||||
void setIncludeAvatars(const QScriptValue& includeAvatars);
|
||||
QVector<QUuid> getIgnoreItems() const;
|
||||
QVector<QUuid> getIncludeItems() const;
|
||||
|
||||
QReadWriteLock* getLock() { return &_lock; }
|
||||
template <typename T>
|
||||
QVector<T> getIgnoreItemsAs() const {
|
||||
QVector<T> result;
|
||||
withReadLock([&] {
|
||||
for (const auto& uid : _ignoreItems) {
|
||||
result.push_back(uid);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
QVector<T> getIncludeItemsAs() const {
|
||||
QVector<T> result;
|
||||
withReadLock([&] {
|
||||
for (const auto& uid : _includeItems) {
|
||||
result.push_back(uid);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
void setIgnoreItems(const QVector<QUuid>& items);
|
||||
void setIncludeItems(const QVector<QUuid>& items);
|
||||
|
||||
private:
|
||||
RayPickFilter _filter;
|
||||
float _maxDistance;
|
||||
const float _maxDistance;
|
||||
bool _enabled;
|
||||
RayPickResult _prevResult;
|
||||
|
||||
QVector<EntityItemID> _ignoreEntities;
|
||||
QVector<EntityItemID> _includeEntities;
|
||||
QVector<OverlayID> _ignoreOverlays;
|
||||
QVector<OverlayID> _includeOverlays;
|
||||
QVector<EntityItemID> _ignoreAvatars;
|
||||
QVector<EntityItemID> _includeAvatars;
|
||||
|
||||
QReadWriteLock _lock;
|
||||
QVector<QUuid> _ignoreItems;
|
||||
QVector<QUuid> _includeItems;
|
||||
};
|
||||
|
||||
#endif // hifi_RayPick_h
|
|
@ -1,7 +1,4 @@
|
|||
//
|
||||
// StaticRayPick.cpp
|
||||
// interface/src/raypick
|
||||
//
|
||||
// Created by Sam Gondelman 7/11/2017
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
|
@ -1,7 +1,4 @@
|
|||
//
|
||||
// StaticRayPick.h
|
||||
// interface/src/raypick
|
||||
//
|
||||
// Created by Sam Gondelman 7/11/2017
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
|
@ -121,8 +121,6 @@ bool Model::needsFixupInScene() const {
|
|||
return (_needsFixupInScene || !_addedToScene) && !_needsReload && isLoaded();
|
||||
}
|
||||
|
||||
// TODO?: should we combine translation and rotation into single method to avoid double-work?
|
||||
// (figure out where we call these)
|
||||
void Model::setTranslation(const glm::vec3& translation) {
|
||||
_translation = translation;
|
||||
updateRenderItems();
|
||||
|
@ -133,6 +131,14 @@ void Model::setRotation(const glm::quat& rotation) {
|
|||
updateRenderItems();
|
||||
}
|
||||
|
||||
// temporary HACK: set transform while avoiding implicit calls to updateRenderItems()
|
||||
// TODO: make setRotation() and friends set flag to be used later to decide to updateRenderItems()
|
||||
void Model::setTransformNoUpdateRenderItems(const Transform& transform) {
|
||||
_translation = transform.getTranslation();
|
||||
_rotation = transform.getRotation();
|
||||
// DO NOT call updateRenderItems() here!
|
||||
}
|
||||
|
||||
Transform Model::getTransform() const {
|
||||
if (_spatiallyNestableOverride) {
|
||||
bool success;
|
||||
|
@ -957,7 +963,7 @@ Blender::Blender(ModelPointer model, int blendNumber, const Geometry::WeakPointe
|
|||
}
|
||||
|
||||
void Blender::run() {
|
||||
PROFILE_RANGE_EX(simulation_animation, __FUNCTION__, 0xFFFF0000, 0, { { "url", _model->getURL().toString() } });
|
||||
DETAILED_PROFILE_RANGE_EX(simulation_animation, __FUNCTION__, 0xFFFF0000, 0, { { "url", _model->getURL().toString() } });
|
||||
QVector<glm::vec3> vertices, normals;
|
||||
if (_model) {
|
||||
int offset = 0;
|
||||
|
@ -1078,8 +1084,7 @@ void Model::snapToRegistrationPoint() {
|
|||
}
|
||||
|
||||
void Model::simulate(float deltaTime, bool fullUpdate) {
|
||||
PROFILE_RANGE(simulation_detail, __FUNCTION__);
|
||||
PerformanceTimer perfTimer("Model::simulate");
|
||||
DETAILED_PROFILE_RANGE(simulation_detail, __FUNCTION__);
|
||||
fullUpdate = updateGeometry() || fullUpdate || (_scaleToFit && !_scaledToFit)
|
||||
|| (_snapModelToRegistrationPoint && !_snappedToRegistrationPoint);
|
||||
|
||||
|
@ -1117,7 +1122,7 @@ void Model::computeMeshPartLocalBounds() {
|
|||
|
||||
// virtual
|
||||
void Model::updateClusterMatrices() {
|
||||
PerformanceTimer perfTimer("Model::updateClusterMatrices");
|
||||
DETAILED_PERFORMANCE_TIMER("Model::updateClusterMatrices");
|
||||
|
||||
if (!_needsUpdateClusterMatrices || !isLoaded()) {
|
||||
return;
|
||||
|
|
|
@ -206,6 +206,7 @@ public:
|
|||
|
||||
void setTranslation(const glm::vec3& translation);
|
||||
void setRotation(const glm::quat& rotation);
|
||||
void setTransformNoUpdateRenderItems(const Transform& transform); // temporary HACK
|
||||
|
||||
const glm::vec3& getTranslation() const { return _translation; }
|
||||
const glm::quat& getRotation() const { return _rotation; }
|
||||
|
|
|
@ -97,5 +97,12 @@ private:
|
|||
static QMap<QString, PerformanceTimerRecord> _records;
|
||||
};
|
||||
|
||||
// uncomment WANT_DETAILED_PERFORMANCE_TIMERS definition to enable performance timers in high-frequency contexts
|
||||
//#define WANT_DETAILED_PERFORMANCE_TIMERS
|
||||
#ifdef WANT_DETAILED_PERFORMANCE_TIMERS
|
||||
#define DETAILED_PERFORMANCE_TIMER(name) PerformanceTimer detailedPerformanceTimer(name);
|
||||
#else // WANT_DETAILED_PERFORMANCE_TIMERS
|
||||
#define DETAILED_PERFORMANCE_TIMER(name) ; // no-op
|
||||
#endif // WANT_DETAILED_PERFORMANCE_TIMERS
|
||||
|
||||
#endif // hifi_PerfStat_h
|
||||
|
|
|
@ -108,4 +108,14 @@ inline void metadata(const QString& metadataType, const QVariantMap& args) {
|
|||
#define SAMPLE_PROFILE_COUNTER(chance, category, name, ...) if (randFloat() <= chance) { PROFILE_COUNTER(category, name, ##__VA_ARGS__); }
|
||||
#define SAMPLE_PROFILE_INSTANT(chance, category, name, ...) if (randFloat() <= chance) { PROFILE_INSTANT(category, name, ##__VA_ARGS__); }
|
||||
|
||||
// uncomment WANT_DETAILED_PROFILING definition to enable profiling in high-frequency contexts
|
||||
//#define WANT_DETAILED_PROFILING
|
||||
#ifdef WANT_DETAILED_PROFILING
|
||||
#define DETAILED_PROFILE_RANGE(category, name) Duration profileRangeThis(trace_##category(), name);
|
||||
#define DETAILED_PROFILE_RANGE_EX(category, name, argbColor, payload, ...) Duration profileRangeThis(trace_##category(), name, argbColor, (uint64_t)payload, ##__VA_ARGS__);
|
||||
#else // WANT_DETAILED_PROFILING
|
||||
#define DETAILED_PROFILE_RANGE(category, name) ; // no-op
|
||||
#define DETAILED_PROFILE_RANGE_EX(category, name, argbColor, payload, ...) ; // no-op
|
||||
#endif // WANT_DETAILED_PROFILING
|
||||
|
||||
#endif
|
||||
|
|
|
@ -23,16 +23,28 @@
|
|||
#include "ToolbarScriptingInterface.h"
|
||||
#include "Logging.h"
|
||||
|
||||
#include <AudioInjector.h>
|
||||
|
||||
#include "SettingHandle.h"
|
||||
|
||||
// FIXME move to global app properties
|
||||
const QString SYSTEM_TOOLBAR = "com.highfidelity.interface.toolbar.system";
|
||||
const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system";
|
||||
const QString TabletScriptingInterface::QML = "hifi/tablet/TabletRoot.qml";
|
||||
|
||||
|
||||
static Setting::Handle<QStringList> tabletSoundsButtonClick("TabletSounds", QStringList { "/sounds/Button06.wav",
|
||||
"/sounds/Button04.wav",
|
||||
"/sounds/Button07.wav",
|
||||
"/sounds/Tab01.wav",
|
||||
"/sounds/Tab02.wav" });
|
||||
|
||||
TabletScriptingInterface::TabletScriptingInterface() {
|
||||
qmlRegisterType<TabletScriptingInterface>("TabletScriptingInterface", 1, 0, "TabletEnums");
|
||||
}
|
||||
|
||||
TabletScriptingInterface::~TabletScriptingInterface() {
|
||||
tabletSoundsButtonClick.set(tabletSoundsButtonClick.get());
|
||||
}
|
||||
|
||||
ToolbarProxy* TabletScriptingInterface::getSystemToolbarProxy() {
|
||||
|
@ -63,6 +75,29 @@ TabletProxy* TabletScriptingInterface::getTablet(const QString& tabletId) {
|
|||
return tabletProxy;
|
||||
}
|
||||
|
||||
void TabletScriptingInterface::preloadSounds() {
|
||||
//preload audio events
|
||||
const QStringList &audioSettings = tabletSoundsButtonClick.get();
|
||||
for (int i = 0; i < TabletAudioEvents::Last; i++) {
|
||||
QFileInfo inf = QFileInfo(PathUtils::resourcesPath() + audioSettings.at(i));
|
||||
SharedSoundPointer sound = DependencyManager::get<SoundCache>()->
|
||||
getSound(QUrl::fromLocalFile(inf.absoluteFilePath()));
|
||||
_audioEvents.insert(static_cast<TabletAudioEvents>(i), sound);
|
||||
}
|
||||
}
|
||||
|
||||
void TabletScriptingInterface::playSound(TabletAudioEvents aEvent) {
|
||||
SharedSoundPointer sound = _audioEvents[aEvent];
|
||||
if (sound) {
|
||||
AudioInjectorOptions options;
|
||||
options.stereo = sound->isStereo();
|
||||
options.ambisonic = sound->isAmbisonic();
|
||||
options.localOnly = true;
|
||||
|
||||
AudioInjectorPointer injector = AudioInjector::playSoundAndDelete(sound->getByteArray(), options);
|
||||
}
|
||||
}
|
||||
|
||||
void TabletScriptingInterface::setToolbarMode(bool toolbarMode) {
|
||||
Q_ASSERT(QThread::currentThread() == qApp->thread());
|
||||
_toolbarMode = toolbarMode;
|
||||
|
@ -323,9 +358,12 @@ void TabletProxy::emitWebEvent(const QVariant& msg) {
|
|||
}
|
||||
|
||||
void TabletProxy::onTabletShown() {
|
||||
if (_tabletShown && _showRunningScripts) {
|
||||
_showRunningScripts = false;
|
||||
pushOntoStack("../../hifi/dialogs/TabletRunningScripts.qml");
|
||||
if (_tabletShown) {
|
||||
static_cast<TabletScriptingInterface*>(parent())->playSound(TabletScriptingInterface::TabletOpen);
|
||||
if (_showRunningScripts) {
|
||||
_showRunningScripts = false;
|
||||
pushOntoStack("../../hifi/dialogs/TabletRunningScripts.qml");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
|
||||
#include "SoundCache.h"
|
||||
#include <DependencyManager.h>
|
||||
|
||||
class ToolbarProxy;
|
||||
|
@ -40,8 +40,11 @@ class OffscreenQmlSurface;
|
|||
class TabletScriptingInterface : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum TabletAudioEvents { ButtonClick, ButtonHover, TabletOpen, TabletHandsIn, TabletHandsOut, Last};
|
||||
Q_ENUM(TabletAudioEvents)
|
||||
|
||||
TabletScriptingInterface();
|
||||
~TabletScriptingInterface();
|
||||
virtual ~TabletScriptingInterface();
|
||||
static const QString QML;
|
||||
|
||||
void setToolbarScriptingInterface(ToolbarScriptingInterface* toolbarScriptingInterface) { _toolbarScriptingInterface = toolbarScriptingInterface; }
|
||||
|
@ -54,6 +57,9 @@ public:
|
|||
*/
|
||||
Q_INVOKABLE TabletProxy* getTablet(const QString& tabletId);
|
||||
|
||||
void preloadSounds();
|
||||
Q_INVOKABLE void playSound(TabletAudioEvents aEvent);
|
||||
|
||||
void setToolbarMode(bool toolbarMode);
|
||||
|
||||
void setQmlTabletRoot(QString tabletId, OffscreenQmlSurface* offscreenQmlSurface);
|
||||
|
@ -77,6 +83,7 @@ private:
|
|||
void processTabletEvents(QObject* object, const QKeyEvent* event);
|
||||
ToolbarProxy* getSystemToolbarProxy();
|
||||
|
||||
QMap<TabletAudioEvents, SharedSoundPointer> _audioEvents;
|
||||
protected:
|
||||
std::map<QString, TabletProxy*> _tabletProxies;
|
||||
ToolbarScriptingInterface* _toolbarScriptingInterface { nullptr };
|
||||
|
|
|
@ -32,7 +32,7 @@ var DEFAULT_SCRIPTS_COMBINED = [
|
|||
"system/tablet-ui/tabletUI.js"
|
||||
];
|
||||
var DEFAULT_SCRIPTS_SEPARATE = [
|
||||
"system/controllers/controllerScripts.js",
|
||||
"system/controllers/controllerScripts.js"
|
||||
// "system/chat.js"
|
||||
];
|
||||
|
||||
|
|
|
@ -141,8 +141,11 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
|||
};
|
||||
|
||||
this.setIgnoreTablet = function() {
|
||||
RayPick.setIgnoreOverlays(_this.leftControllerRayPick, [HMD.tabletID]);
|
||||
RayPick.setIgnoreOverlays(_this.rightControllerRayPick, [HMD.tabletID]);
|
||||
if (HMD.tabletID !== this.tabletID) {
|
||||
this.tabletID = HMD.tabletID;
|
||||
RayPick.setIgnoreItems(_this.leftControllerRayPick, _this.blacklist.concat([HMD.tabletID]));
|
||||
RayPick.setIgnoreItems(_this.rightControllerRayPick, _this.blacklist.concat([HMD.tabletID]));
|
||||
}
|
||||
};
|
||||
|
||||
this.update = function () {
|
||||
|
@ -367,9 +370,8 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
|||
};
|
||||
|
||||
this.setBlacklist = function() {
|
||||
RayPick.setIgnoreEntities(_this.leftControllerRayPick, this.blacklist);
|
||||
RayPick.setIgnoreEntities(_this.rightControllerRayPick, this.blacklist);
|
||||
|
||||
RayPick.setIgnoreItems(_this.leftControllerRayPick, this.blacklist.concat(HMD.tabletID));
|
||||
RayPick.setIgnoreItems(_this.rightControllerRayPick, this.blacklist.concat(HMD.tabletID));
|
||||
};
|
||||
|
||||
var MAPPING_NAME = "com.highfidelity.controllerDispatcher";
|
||||
|
|
|
@ -127,6 +127,13 @@ Script.include("/~/system/libraries/utils.js");
|
|||
this.updateLaserPointer = function(controllerData) {
|
||||
LaserPointers.enableLaserPointer(this.laserPointer);
|
||||
LaserPointers.setRenderState(this.laserPointer, this.mode);
|
||||
|
||||
if (HMD.tabletID !== this.tabletID || HMD.tabletButtonID !== this.tabletButtonID || HMD.tabletScreenID !== this.tabletScreenID) {
|
||||
this.tabletID = HMD.tabletID;
|
||||
this.tabletButtonID = HMD.tabletButtonID;
|
||||
this.tabletScreenID = HMD.tabletScreenID;
|
||||
LaserPointers.setIgnoreItems(this.laserPointer, [HMD.tabletID, HMD.tabletButtonID, HMD.tabletScreenID]);
|
||||
}
|
||||
};
|
||||
|
||||
this.pointingAtTablet = function(objectID) {
|
||||
|
@ -233,7 +240,7 @@ Script.include("/~/system/libraries/utils.js");
|
|||
defaultRenderStates: defaultRenderStates
|
||||
});
|
||||
|
||||
LaserPointers.setIgnoreOverlays(this.laserPointer, [HMD.tabletID, HMD.tabletButtonID, HMD.tabletScreenID]);
|
||||
LaserPointers.setIgnoreItems(this.laserPointer, [HMD.tabletID, HMD.tabletButtonID, HMD.tabletScreenID]);
|
||||
}
|
||||
|
||||
var leftHandInEditMode = new InEditMode(LEFT_HAND);
|
||||
|
|
|
@ -177,6 +177,11 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
this.updateLaserPointer = function(controllerData) {
|
||||
LaserPointers.enableLaserPointer(this.laserPointer);
|
||||
LaserPointers.setRenderState(this.laserPointer, this.mode);
|
||||
|
||||
if (HMD.tabletID !== this.tabletID) {
|
||||
this.tabletID = HMD.tabletID;
|
||||
LaserPointers.setIgnoreItems(this.laserPointer, [HMD.tabletID]);
|
||||
}
|
||||
};
|
||||
|
||||
this.processControllerTriggers = function(controllerData) {
|
||||
|
@ -369,7 +374,7 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
defaultRenderStates: defaultRenderStates
|
||||
});
|
||||
|
||||
LaserPointers.setIgnoreOverlays(this.laserPointer, [HMD.tabletID]);
|
||||
LaserPointers.setIgnoreItems(this.laserPointer, [HMD.tabletID]);
|
||||
}
|
||||
|
||||
var leftOverlayLaserInput = new OverlayLaserInput(LEFT_HAND);
|
||||
|
|
|
@ -349,10 +349,10 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
};
|
||||
|
||||
this.setIgnoreEntities = function(entitiesToIgnore) {
|
||||
LaserPointers.setIgnoreEntities(this.teleportRayHandVisible, entitiesToIgnore);
|
||||
LaserPointers.setIgnoreEntities(this.teleportRayHandInvisible, entitiesToIgnore);
|
||||
LaserPointers.setIgnoreEntities(this.teleportRayHeadVisible, entitiesToIgnore);
|
||||
LaserPointers.setIgnoreEntities(this.teleportRayHeadInvisible, entitiesToIgnore);
|
||||
LaserPointers.setIgnoreItems(this.teleportRayHandVisible, entitiesToIgnore);
|
||||
LaserPointers.setIgnoreItems(this.teleportRayHandInvisible, entitiesToIgnore);
|
||||
LaserPointers.setIgnoreItems(this.teleportRayHeadVisible, entitiesToIgnore);
|
||||
LaserPointers.setIgnoreItems(this.teleportRayHeadInvisible, entitiesToIgnore);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue