Merge branch 'master' of github.com:highfidelity/hifi into discovery_appUi
|
@ -332,6 +332,10 @@ if (APPLE)
|
||||||
COMMAND "${CMAKE_COMMAND}" -E copy_directory
|
COMMAND "${CMAKE_COMMAND}" -E copy_directory
|
||||||
"${PROJECT_SOURCE_DIR}/resources/fonts"
|
"${PROJECT_SOURCE_DIR}/resources/fonts"
|
||||||
"${RESOURCES_DEV_DIR}/fonts"
|
"${RESOURCES_DEV_DIR}/fonts"
|
||||||
|
# add redirect json to macOS builds.
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
|
||||||
|
"${PROJECT_SOURCE_DIR}/resources/serverless/redirect.json"
|
||||||
|
"${RESOURCES_DEV_DIR}/serverless/redirect.json"
|
||||||
)
|
)
|
||||||
|
|
||||||
# call the fixup_interface macro to add required bundling commands for installation
|
# call the fixup_interface macro to add required bundling commands for installation
|
||||||
|
@ -360,6 +364,9 @@ else()
|
||||||
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
|
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
|
||||||
"${PROJECT_SOURCE_DIR}/resources/serverless/tutorial.json"
|
"${PROJECT_SOURCE_DIR}/resources/serverless/tutorial.json"
|
||||||
"${RESOURCES_DEV_DIR}/serverless/tutorial.json"
|
"${RESOURCES_DEV_DIR}/serverless/tutorial.json"
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
|
||||||
|
"${PROJECT_SOURCE_DIR}/resources/serverless/redirect.json"
|
||||||
|
"${RESOURCES_DEV_DIR}/serverless/redirect.json"
|
||||||
# copy JSDoc files beside the executable
|
# copy JSDoc files beside the executable
|
||||||
COMMAND "${CMAKE_COMMAND}" -E copy_directory
|
COMMAND "${CMAKE_COMMAND}" -E copy_directory
|
||||||
"${CMAKE_SOURCE_DIR}/tools/jsdoc/out"
|
"${CMAKE_SOURCE_DIR}/tools/jsdoc/out"
|
||||||
|
|
5
interface/resources/images/eyeClosed.svg
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<svg width="31" height="23" viewBox="0 0 31 23" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.59534 11.0156C6.16042 13.4128 9.65987 15.5898 13.6042 16.1774C17.686 16.7856 22.4164 15.7196 27.3057 11.0659C22.0721 6.07309 17.0642 5.14115 12.9153 5.90073C8.99427 6.61859 5.69298 8.87688 3.59534 11.0156ZM12.455 3.27591C17.7727 2.30235 23.9836 3.74895 30.1053 10.1333L31 11.0664L30.1053 11.9994C24.3636 17.9875 18.4774 19.5983 13.2276 18.8161C8.06048 18.0463 3.70384 14.9892 0.837069 11.9994L0 11.1265L0.778477 10.1986C3.05338 7.48717 7.2318 4.23217 12.455 3.27591Z" fill="#3D3D3D"/>
|
||||||
|
<ellipse cx="15.6539" cy="10.9218" rx="3.65386" ry="3.81061" fill="#3D3D3D"/>
|
||||||
|
<line x1="25" y1="2.12132" x2="7.12132" y2="20" stroke="#3D3D3D" stroke-width="3" stroke-linecap="round"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 825 B |
4
interface/resources/images/eyeOpen.svg
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<svg width="31" height="16" viewBox="0 0 31 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.59534 8.01564C6.16042 10.4128 9.65987 12.5898 13.6042 13.1774C17.686 13.7856 22.4164 12.7196 27.3057 8.06585C22.0721 3.07309 17.0642 2.14115 12.9153 2.90073C8.99427 3.61859 5.69298 5.87688 3.59534 8.01564ZM12.455 0.275915C17.7727 -0.697651 23.9836 0.748949 30.1053 7.13329L31 8.06636L30.1053 8.99944C24.3636 14.9875 18.4774 16.5983 13.2276 15.8161C8.06048 15.0463 3.70384 11.9892 0.837069 8.99944L0 8.12646L0.778477 7.1986C3.05338 4.48717 7.2318 1.23217 12.455 0.275915Z" fill="#3D3D3D"/>
|
||||||
|
<ellipse cx="15.644" cy="7.92179" rx="3.65386" ry="3.81061" fill="#3D3D3D"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 721 B |
BIN
interface/resources/images/loadingBar_placard.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
interface/resources/images/loadingBar_progress.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
interface/resources/meshes/redirect/oopsDialog_auth.fbx
Normal file
BIN
interface/resources/meshes/redirect/oopsDialog_auth.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
interface/resources/meshes/redirect/oopsDialog_protocol.fbx
Normal file
BIN
interface/resources/meshes/redirect/oopsDialog_protocol.png
Normal file
After Width: | Height: | Size: 4.8 KiB |
BIN
interface/resources/meshes/redirect/oopsDialog_vague.fbx
Normal file
BIN
interface/resources/meshes/redirect/oopsDialog_vague.png
Normal file
After Width: | Height: | Size: 5 KiB |
|
@ -23,6 +23,7 @@ ModalWindow {
|
||||||
objectName: "LoginDialog"
|
objectName: "LoginDialog"
|
||||||
implicitWidth: 520
|
implicitWidth: 520
|
||||||
implicitHeight: 320
|
implicitHeight: 320
|
||||||
|
closeButtonVisible: true
|
||||||
destroyOnCloseButton: true
|
destroyOnCloseButton: true
|
||||||
destroyOnHidden: true
|
destroyOnHidden: true
|
||||||
visible: true
|
visible: true
|
||||||
|
|
|
@ -117,27 +117,27 @@ Item {
|
||||||
}
|
}
|
||||||
spacing: hifi.dimensions.contentSpacing.y / 2
|
spacing: hifi.dimensions.contentSpacing.y / 2
|
||||||
|
|
||||||
TextField {
|
TextField {
|
||||||
id: usernameField
|
id: usernameField
|
||||||
anchors {
|
anchors {
|
||||||
horizontalCenter: parent.horizontalCenter
|
horizontalCenter: parent.horizontalCenter
|
||||||
}
|
|
||||||
width: 1080
|
|
||||||
placeholderText: qsTr("Username or Email")
|
|
||||||
}
|
}
|
||||||
|
width: 1080
|
||||||
|
placeholderText: qsTr("Username or Email")
|
||||||
|
}
|
||||||
|
|
||||||
TextField {
|
TextField {
|
||||||
id: passwordField
|
id: passwordField
|
||||||
anchors {
|
anchors {
|
||||||
horizontalCenter: parent.horizontalCenter
|
horizontalCenter: parent.horizontalCenter
|
||||||
}
|
|
||||||
width: 1080
|
|
||||||
|
|
||||||
placeholderText: qsTr("Password")
|
|
||||||
echoMode: TextInput.Password
|
|
||||||
|
|
||||||
Keys.onReturnPressed: linkAccountBody.login()
|
|
||||||
}
|
}
|
||||||
|
width: 1080
|
||||||
|
|
||||||
|
placeholderText: qsTr("Password")
|
||||||
|
echoMode: TextInput.Password
|
||||||
|
|
||||||
|
Keys.onReturnPressed: linkAccountBody.login()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
InfoItem {
|
InfoItem {
|
||||||
|
@ -176,7 +176,7 @@ Item {
|
||||||
anchors {
|
anchors {
|
||||||
left: parent.left
|
left: parent.left
|
||||||
top: form.bottom
|
top: form.bottom
|
||||||
topMargin: hifi.dimensions.contentSpacing.y / 2
|
topMargin: hifi.dimensions.contentSpacing.y / 2
|
||||||
}
|
}
|
||||||
|
|
||||||
spacing: hifi.dimensions.contentSpacing.x
|
spacing: hifi.dimensions.contentSpacing.x
|
||||||
|
@ -201,7 +201,7 @@ Item {
|
||||||
anchors {
|
anchors {
|
||||||
right: parent.right
|
right: parent.right
|
||||||
top: form.bottom
|
top: form.bottom
|
||||||
topMargin: hifi.dimensions.contentSpacing.y / 2
|
topMargin: hifi.dimensions.contentSpacing.y / 2
|
||||||
}
|
}
|
||||||
spacing: hifi.dimensions.contentSpacing.x
|
spacing: hifi.dimensions.contentSpacing.x
|
||||||
onHeightChanged: d.resize(); onWidthChanged: d.resize();
|
onHeightChanged: d.resize(); onWidthChanged: d.resize();
|
||||||
|
|
|
@ -15,7 +15,6 @@ import QtQuick.Controls.Styles 1.4 as OriginalStyles
|
||||||
|
|
||||||
import "../controls-uit"
|
import "../controls-uit"
|
||||||
import "../styles-uit"
|
import "../styles-uit"
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: linkAccountBody
|
id: linkAccountBody
|
||||||
clip: true
|
clip: true
|
||||||
|
@ -87,6 +86,23 @@ Item {
|
||||||
height: 48
|
height: 48
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ShortcutText {
|
||||||
|
id: flavorText
|
||||||
|
anchors {
|
||||||
|
top: parent.top
|
||||||
|
left: parent.left
|
||||||
|
margins: 0
|
||||||
|
topMargin: hifi.dimensions.contentSpacing.y
|
||||||
|
}
|
||||||
|
|
||||||
|
text: qsTr("Sign in to High Fidelity to make friends, get HFC, and buy interesting things on the Marketplace!")
|
||||||
|
width: parent.width
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
lineHeight: 1
|
||||||
|
lineHeightMode: Text.ProportionalHeight
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
}
|
||||||
|
|
||||||
ShortcutText {
|
ShortcutText {
|
||||||
id: mainTextContainer
|
id: mainTextContainer
|
||||||
anchors {
|
anchors {
|
||||||
|
@ -97,7 +113,6 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
visible: false
|
visible: false
|
||||||
|
|
||||||
text: qsTr("Username or password incorrect.")
|
text: qsTr("Username or password incorrect.")
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
color: hifi.colors.redAccent
|
color: hifi.colors.redAccent
|
||||||
|
@ -117,22 +132,21 @@ Item {
|
||||||
}
|
}
|
||||||
spacing: 2 * hifi.dimensions.contentSpacing.y
|
spacing: 2 * hifi.dimensions.contentSpacing.y
|
||||||
|
|
||||||
|
|
||||||
TextField {
|
TextField {
|
||||||
id: usernameField
|
id: usernameField
|
||||||
text: Settings.getValue("wallet/savedUsername", "");
|
text: Settings.getValue("wallet/savedUsername", "");
|
||||||
width: parent.width
|
width: parent.width
|
||||||
focus: true
|
focus: true
|
||||||
label: "Username or Email"
|
placeholderText: "Username or Email"
|
||||||
activeFocusOnPress: true
|
activeFocusOnPress: true
|
||||||
|
|
||||||
ShortcutText {
|
ShortcutText {
|
||||||
z: 10
|
z: 10
|
||||||
|
y: usernameField.height
|
||||||
anchors {
|
anchors {
|
||||||
left: usernameField.left
|
right: usernameField.right
|
||||||
top: usernameField.top
|
top: usernameField.bottom
|
||||||
leftMargin: usernameField.textFieldLabel.contentWidth + 10
|
topMargin: 4
|
||||||
topMargin: -19
|
|
||||||
}
|
}
|
||||||
|
|
||||||
text: "<a href='https://highfidelity.com/users/password/new'>Forgot Username?</a>"
|
text: "<a href='https://highfidelity.com/users/password/new'>Forgot Username?</a>"
|
||||||
|
@ -143,26 +157,32 @@ Item {
|
||||||
|
|
||||||
onLinkActivated: loginDialog.openUrl(link)
|
onLinkActivated: loginDialog.openUrl(link)
|
||||||
}
|
}
|
||||||
|
|
||||||
onFocusChanged: {
|
onFocusChanged: {
|
||||||
root.text = "";
|
root.text = "";
|
||||||
}
|
}
|
||||||
|
Component.onCompleted: {
|
||||||
|
var savedUsername = Settings.getValue("wallet/savedUsername", "");
|
||||||
|
usernameField.text = savedUsername === "Unknown user" ? "" : savedUsername;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TextField {
|
TextField {
|
||||||
id: passwordField
|
id: passwordField
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
placeholderText: "Password"
|
||||||
label: "Password"
|
|
||||||
echoMode: showPassword.checked ? TextInput.Normal : TextInput.Password
|
|
||||||
activeFocusOnPress: true
|
activeFocusOnPress: true
|
||||||
|
echoMode: TextInput.Password
|
||||||
|
onHeightChanged: d.resize(); onWidthChanged: d.resize();
|
||||||
|
|
||||||
ShortcutText {
|
ShortcutText {
|
||||||
|
id: forgotPasswordShortcut
|
||||||
|
y: passwordField.height
|
||||||
z: 10
|
z: 10
|
||||||
anchors {
|
anchors {
|
||||||
left: passwordField.left
|
right: passwordField.right
|
||||||
top: passwordField.top
|
top: passwordField.bottom
|
||||||
leftMargin: passwordField.textFieldLabel.contentWidth + 10
|
topMargin: 4
|
||||||
topMargin: -19
|
|
||||||
}
|
}
|
||||||
|
|
||||||
text: "<a href='https://highfidelity.com/users/password/new'>Forgot Password?</a>"
|
text: "<a href='https://highfidelity.com/users/password/new'>Forgot Password?</a>"
|
||||||
|
@ -179,12 +199,45 @@ Item {
|
||||||
root.isPassword = true;
|
root.isPassword = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Keys.onReturnPressed: linkAccountBody.login()
|
Rectangle {
|
||||||
}
|
id: showPasswordHitbox
|
||||||
|
z: 10
|
||||||
|
x: passwordField.width - ((passwordField.height) * 31 / 23)
|
||||||
|
width: parent.width - (parent.width - (parent.height * 31/16))
|
||||||
|
height: parent.height
|
||||||
|
anchors {
|
||||||
|
right: parent.right
|
||||||
|
}
|
||||||
|
color: "transparent"
|
||||||
|
|
||||||
CheckBox {
|
Image {
|
||||||
id: showPassword
|
id: showPasswordImage
|
||||||
text: "Show password"
|
y: (passwordField.height - (passwordField.height * 16 / 23)) / 2
|
||||||
|
width: passwordField.width - (passwordField.width - (((passwordField.height) * 31/23)))
|
||||||
|
height: passwordField.height * 16 / 23
|
||||||
|
anchors {
|
||||||
|
right: parent.right
|
||||||
|
rightMargin: 3
|
||||||
|
}
|
||||||
|
source: "../../images/eyeOpen.svg"
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: passwordFieldMouseArea
|
||||||
|
anchors.fill: parent
|
||||||
|
acceptedButtons: Qt.LeftButton
|
||||||
|
property bool showPassword: false
|
||||||
|
onClicked: {
|
||||||
|
showPassword = !showPassword;
|
||||||
|
passwordField.echoMode = showPassword ? TextInput.Normal : TextInput.Password;
|
||||||
|
showPasswordImage.source = showPassword ? "../../images/eyeClosed.svg" : "../../images/eyeOpen.svg";
|
||||||
|
showPasswordImage.height = showPassword ? passwordField.height : passwordField.height * 16 / 23;
|
||||||
|
showPasswordImage.y = showPassword ? 0 : (passwordField.height - showPasswordImage.height) / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onReturnPressed: linkAccountBody.login()
|
||||||
}
|
}
|
||||||
|
|
||||||
InfoItem {
|
InfoItem {
|
||||||
|
@ -206,6 +259,26 @@ Item {
|
||||||
onHeightChanged: d.resize(); onWidthChanged: d.resize();
|
onHeightChanged: d.resize(); onWidthChanged: d.resize();
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
|
||||||
|
CheckBox {
|
||||||
|
id: autoLogoutCheckbox
|
||||||
|
checked: !Settings.getValue("wallet/autoLogout", true)
|
||||||
|
text: "Keep me signed in"
|
||||||
|
boxSize: 20;
|
||||||
|
labelFontSize: 15
|
||||||
|
color: hifi.colors.black
|
||||||
|
onCheckedChanged: {
|
||||||
|
Settings.setValue("wallet/autoLogout", !checked);
|
||||||
|
if (checked) {
|
||||||
|
Settings.setValue("wallet/savedUsername", Account.username);
|
||||||
|
} else {
|
||||||
|
Settings.setValue("wallet/savedUsername", "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Component.onDestruction: {
|
||||||
|
Settings.setValue("wallet/autoLogout", !checked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
id: linkAccountButton
|
id: linkAccountButton
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
@ -216,12 +289,6 @@ Item {
|
||||||
|
|
||||||
onClicked: linkAccountBody.login()
|
onClicked: linkAccountBody.login()
|
||||||
}
|
}
|
||||||
|
|
||||||
Button {
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
text: qsTr("Cancel")
|
|
||||||
onClicked: root.tryDestroy()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
|
@ -234,7 +301,7 @@ Item {
|
||||||
RalewaySemiBold {
|
RalewaySemiBold {
|
||||||
size: hifi.fontSizes.inputLabel
|
size: hifi.fontSizes.inputLabel
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
text: qsTr("Don't have an account?")
|
text: qsTr("New to High Fidelity?")
|
||||||
}
|
}
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
|
@ -287,11 +354,23 @@ Item {
|
||||||
bodyLoader.item.width = root.pane.width
|
bodyLoader.item.width = root.pane.width
|
||||||
bodyLoader.item.height = root.pane.height
|
bodyLoader.item.height = root.pane.height
|
||||||
}
|
}
|
||||||
|
if (Settings.getValue("loginDialogPoppedUp", false)) {
|
||||||
|
var data = {
|
||||||
|
"action": "user logged in"
|
||||||
|
};
|
||||||
|
UserActivityLogger.logAction("encourageLoginDialog", data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onHandleLoginFailed: {
|
onHandleLoginFailed: {
|
||||||
console.log("Login Failed")
|
console.log("Login Failed")
|
||||||
mainTextContainer.visible = true
|
mainTextContainer.visible = true
|
||||||
toggleLoading(false)
|
toggleLoading(false)
|
||||||
|
if (Settings.getValue("loginDialogPoppedUp", false)) {
|
||||||
|
var data = {
|
||||||
|
"action": "user failed logging in"
|
||||||
|
};
|
||||||
|
UserActivityLogger.logAction("encourageLoginDialog", data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onHandleLinkCompleted: {
|
onHandleLinkCompleted: {
|
||||||
console.log("Link Succeeded")
|
console.log("Link Succeeded")
|
||||||
|
|
|
@ -175,7 +175,14 @@ Rectangle {
|
||||||
displayNameInput.text = getAvatarsData.displayName;
|
displayNameInput.text = getAvatarsData.displayName;
|
||||||
currentAvatarSettings = getAvatarsData.currentAvatarSettings;
|
currentAvatarSettings = getAvatarsData.currentAvatarSettings;
|
||||||
|
|
||||||
updateCurrentAvatarInBookmarks(currentAvatar);
|
var bookmarkAvatarIndex = allAvatars.findAvatarIndexByValue(currentAvatar);
|
||||||
|
if (bookmarkAvatarIndex === -1) {
|
||||||
|
currentAvatar.name = '';
|
||||||
|
} else {
|
||||||
|
currentAvatar.name = allAvatars.get(bookmarkAvatarIndex).name;
|
||||||
|
allAvatars.move(bookmarkAvatarIndex, 0, 1);
|
||||||
|
}
|
||||||
|
view.setPage(0);
|
||||||
} else if (message.method === 'updateAvatarInBookmarks') {
|
} else if (message.method === 'updateAvatarInBookmarks') {
|
||||||
updateCurrentAvatarInBookmarks(currentAvatar);
|
updateCurrentAvatarInBookmarks(currentAvatar);
|
||||||
} else if (message.method === 'selectAvatarEntity') {
|
} else if (message.method === 'selectAvatarEntity') {
|
||||||
|
|
|
@ -79,7 +79,7 @@ StackView {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
location.text = targetString;
|
location.text = targetString;
|
||||||
toggleOrGo(true, targetString);
|
toggleOrGo(targetString, true);
|
||||||
clearAddressLineTimer.start();
|
clearAddressLineTimer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -399,7 +399,7 @@ StackView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleOrGo(fromSuggestions, address) {
|
function toggleOrGo(address, fromSuggestions) {
|
||||||
if (address !== undefined && address !== "") {
|
if (address !== undefined && address !== "") {
|
||||||
addressBarDialog.loadAddress(address, fromSuggestions);
|
addressBarDialog.loadAddress(address, fromSuggestions);
|
||||||
clearAddressLineTimer.start();
|
clearAddressLineTimer.start();
|
||||||
|
|
|
@ -94,5 +94,25 @@ Frame {
|
||||||
color: hifi.colors.lightGray
|
color: hifi.colors.lightGray
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GlyphButton {
|
||||||
|
id: closeButton
|
||||||
|
visible: window.closeButtonVisible
|
||||||
|
width: 30
|
||||||
|
y: -hifi.dimensions.modalDialogTitleHeight
|
||||||
|
anchors {
|
||||||
|
top: parent.top
|
||||||
|
right: parent.right
|
||||||
|
topMargin: 10
|
||||||
|
rightMargin: 10
|
||||||
|
}
|
||||||
|
glyph: hifi.glyphs.close
|
||||||
|
size: 23
|
||||||
|
onClicked: {
|
||||||
|
window.clickedCloseButton = true;
|
||||||
|
window.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,9 @@ ScrollingWindow {
|
||||||
destroyOnHidden: true
|
destroyOnHidden: true
|
||||||
frame: ModalFrame { }
|
frame: ModalFrame { }
|
||||||
|
|
||||||
|
property bool closeButtonVisible: false
|
||||||
|
// only applicable for if close button is visible.
|
||||||
|
property bool clickedCloseButton: false
|
||||||
property int colorScheme: hifi.colorSchemes.light
|
property int colorScheme: hifi.colorSchemes.light
|
||||||
property bool draggable: false
|
property bool draggable: false
|
||||||
|
|
||||||
|
|
934
interface/resources/serverless/redirect.json
Normal file
|
@ -0,0 +1,934 @@
|
||||||
|
{
|
||||||
|
"DataVersion": 0,
|
||||||
|
"Paths":
|
||||||
|
{
|
||||||
|
"/": "/4,1.4,4/0,0.49544,0,0.868645"
|
||||||
|
},
|
||||||
|
"Entities": [
|
||||||
|
{
|
||||||
|
"clientOnly": false,
|
||||||
|
"collidesWith": "static,dynamic,kinematic,otherAvatar,",
|
||||||
|
"collisionMask": 23,
|
||||||
|
"created": "2018-09-05T18:13:00Z",
|
||||||
|
"dimensions": {
|
||||||
|
"blue": 1.159199833869934,
|
||||||
|
"green": 2.8062009811401367,
|
||||||
|
"red": 1.6216505765914917,
|
||||||
|
"x": 1.6216505765914917,
|
||||||
|
"y": 2.8062009811401367,
|
||||||
|
"z": 1.159199833869934
|
||||||
|
},
|
||||||
|
"id": "{d0ed60b8-9174-4c56-8e78-2c5399329ae0}",
|
||||||
|
"lastEdited": 1536171372916208,
|
||||||
|
"lastEditedBy": "{151cb20e-715a-4c80-aa0d-5b58b1c8a0c9}",
|
||||||
|
"locked": true,
|
||||||
|
"name": "Try Again Zone",
|
||||||
|
"owningAvatarID": "{00000000-0000-0000-0000-000000000000}",
|
||||||
|
"position": {
|
||||||
|
"blue":4.015342712402344,
|
||||||
|
"green":1.649999976158142,
|
||||||
|
"red":2.00921893119812,
|
||||||
|
"x":2.00921893119812,
|
||||||
|
"y":1.649999976158142,
|
||||||
|
"z":4.015342712402344
|
||||||
|
},
|
||||||
|
"queryAACube": {
|
||||||
|
"scale": 3.4421300888061523,
|
||||||
|
"x": 1.6001315116882324,
|
||||||
|
"y": -0.07100248336791992,
|
||||||
|
"z": 0.14220571517944336
|
||||||
|
},
|
||||||
|
"rotation": {
|
||||||
|
"w": 0.9914448857307434,
|
||||||
|
"x": 0,
|
||||||
|
"y": -0.13052619993686676,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"script": "https://hifi-content.s3.amazonaws.com/wayne/404redirectionScripts/zoneTryAgainEntityScript.js",
|
||||||
|
"shapeType": "box",
|
||||||
|
"type": "Zone",
|
||||||
|
"userData": "{\"grabbableKey\":{\"grabbable\":false}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"clientOnly": false,
|
||||||
|
"color": {
|
||||||
|
"blue": 0,
|
||||||
|
"green": 0,
|
||||||
|
"red": 255
|
||||||
|
},
|
||||||
|
"created": "2018-09-05T00:40:03Z",
|
||||||
|
"dimensions": {
|
||||||
|
"blue": 8.645400047302246,
|
||||||
|
"green": 0.20000000298023224,
|
||||||
|
"red": 20.025121688842773,
|
||||||
|
"x": 20.025121688842773,
|
||||||
|
"y": 0.20000000298023224,
|
||||||
|
"z": 8.645400047302246
|
||||||
|
},
|
||||||
|
"id": "{e44fb546-b34a-4966-9b11-73556f800d21}",
|
||||||
|
"lastEdited": 1536107948776951,
|
||||||
|
"lastEditedBy": "{ce82d352-3002-44ae-9b76-66492989a1db}",
|
||||||
|
"locked": true,
|
||||||
|
"name": "ceiling",
|
||||||
|
"owningAvatarID": "{00000000-0000-0000-0000-000000000000}",
|
||||||
|
"position": {
|
||||||
|
"blue": 4.846520900726318,
|
||||||
|
"green": 2.912982940673828,
|
||||||
|
"red": 5.739595890045166,
|
||||||
|
"x": 5.739595890045166,
|
||||||
|
"y": 2.912982940673828,
|
||||||
|
"z": 4.846520900726318
|
||||||
|
},
|
||||||
|
"queryAACube": {
|
||||||
|
"scale": 21.812576293945312,
|
||||||
|
"x": -5.16669225692749,
|
||||||
|
"y": -7.993305206298828,
|
||||||
|
"z": -6.059767246246338
|
||||||
|
},
|
||||||
|
"rotation": {
|
||||||
|
"w": 0.970295786857605,
|
||||||
|
"x": 0,
|
||||||
|
"y": -0.24192190170288086,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"shape": "Cube",
|
||||||
|
"type": "Box",
|
||||||
|
"userData": "{\"grabbableKey\":{\"grabbable\":false}}",
|
||||||
|
"visible": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"clientOnly": false,
|
||||||
|
"color": {
|
||||||
|
"blue": 0,
|
||||||
|
"green": 0,
|
||||||
|
"red": 0
|
||||||
|
},
|
||||||
|
"created": "2018-09-05T00:40:03Z",
|
||||||
|
"dimensions": {
|
||||||
|
"blue": 6.9401350021362305,
|
||||||
|
"green": 0.04553089290857315,
|
||||||
|
"red": 7.004304885864258,
|
||||||
|
"x": 7.004304885864258,
|
||||||
|
"y": 0.04553089290857315,
|
||||||
|
"z": 6.9401350021362305
|
||||||
|
},
|
||||||
|
"id": "{8cd93fe5-16c0-44b7-b1e9-e7e06c4e9228}",
|
||||||
|
"lastEdited": 1536107948774796,
|
||||||
|
"lastEditedBy": "{4eecd88f-ef9b-4a83-bb9a-7f7496209c6b}",
|
||||||
|
"locked": true,
|
||||||
|
"name": "floor",
|
||||||
|
"owningAvatarID": "{00000000-0000-0000-0000-000000000000}",
|
||||||
|
"position": {
|
||||||
|
"blue": 3.6175529956817627,
|
||||||
|
"green": 0,
|
||||||
|
"red": 4.102385997772217,
|
||||||
|
"x": 4.102385997772217,
|
||||||
|
"y": 0,
|
||||||
|
"z": 3.6175529956817627
|
||||||
|
},
|
||||||
|
"queryAACube": {
|
||||||
|
"scale": 9.860417366027832,
|
||||||
|
"x": -0.8278226852416992,
|
||||||
|
"y": -4.930208683013916,
|
||||||
|
"z": -1.3126556873321533
|
||||||
|
},
|
||||||
|
"rotation": {
|
||||||
|
"w": 0.8660253882408142,
|
||||||
|
"x": -1.5922749298624694e-05,
|
||||||
|
"y": 0.5,
|
||||||
|
"z": -4.572480611386709e-05
|
||||||
|
},
|
||||||
|
"shape": "Cube",
|
||||||
|
"type": "Box",
|
||||||
|
"userData": "{\"grabbableKey\":{\"grabbable\":false}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"clientOnly": false,
|
||||||
|
"color": {
|
||||||
|
"blue": 0,
|
||||||
|
"green": 0,
|
||||||
|
"red": 0
|
||||||
|
},
|
||||||
|
"created": "2018-09-05T00:40:03Z",
|
||||||
|
"dimensions": {
|
||||||
|
"blue": 11.117486953735352,
|
||||||
|
"green": 3.580313205718994,
|
||||||
|
"red": 0.20000000298023224,
|
||||||
|
"x": 0.20000000298023224,
|
||||||
|
"y": 3.580313205718994,
|
||||||
|
"z": 11.117486953735352
|
||||||
|
},
|
||||||
|
"id": "{147272dc-a344-4171-9621-efc1c2095997}",
|
||||||
|
"lastEdited": 1536107948776823,
|
||||||
|
"lastEditedBy": "{ce82d352-3002-44ae-9b76-66492989a1db}",
|
||||||
|
"locked": true,
|
||||||
|
"name": "leftWall",
|
||||||
|
"owningAvatarID": "{00000000-0000-0000-0000-000000000000}",
|
||||||
|
"position": {
|
||||||
|
"blue": 6.1806135177612305,
|
||||||
|
"green": 1.0066027641296387,
|
||||||
|
"red": 1.4690406322479248,
|
||||||
|
"x": 1.4690406322479248,
|
||||||
|
"y": 1.0066027641296387,
|
||||||
|
"z": 6.1806135177612305
|
||||||
|
},
|
||||||
|
"queryAACube": {
|
||||||
|
"scale": 11.681488037109375,
|
||||||
|
"x": -4.371703147888184,
|
||||||
|
"y": -4.834141254425049,
|
||||||
|
"z": 0.33986949920654297
|
||||||
|
},
|
||||||
|
"rotation": {
|
||||||
|
"w": 0.8637980222702026,
|
||||||
|
"x": -4.57763671875e-05,
|
||||||
|
"y": 0.5038070678710938,
|
||||||
|
"z": -1.52587890625e-05
|
||||||
|
},
|
||||||
|
"shape": "Cube",
|
||||||
|
"type": "Box",
|
||||||
|
"userData": "{\"grabbableKey\":{\"grabbable\":false}}",
|
||||||
|
"visible": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"clientOnly": false,
|
||||||
|
"color": {
|
||||||
|
"blue": 0,
|
||||||
|
"green": 0,
|
||||||
|
"red": 0
|
||||||
|
},
|
||||||
|
"created": "2018-09-05T00:40:03Z",
|
||||||
|
"dimensions": {
|
||||||
|
"blue": 11.117486953735352,
|
||||||
|
"green": 3.580313205718994,
|
||||||
|
"red": 0.20000000298023224,
|
||||||
|
"x": 0.20000000298023224,
|
||||||
|
"y": 3.580313205718994,
|
||||||
|
"z": 11.117486953735352
|
||||||
|
},
|
||||||
|
"id": "{5f2b89b8-47e3-4915-a966-d46307a40f06}",
|
||||||
|
"lastEdited": 1536107948774605,
|
||||||
|
"lastEditedBy": "{ce82d352-3002-44ae-9b76-66492989a1db}",
|
||||||
|
"locked": true,
|
||||||
|
"name": "backWall",
|
||||||
|
"owningAvatarID": "{00000000-0000-0000-0000-000000000000}",
|
||||||
|
"position": {
|
||||||
|
"blue": 5.268576622009277,
|
||||||
|
"green": 1.0066027641296387,
|
||||||
|
"red": 6.093774318695068,
|
||||||
|
"x": 6.093774318695068,
|
||||||
|
"y": 1.0066027641296387,
|
||||||
|
"z": 5.268576622009277
|
||||||
|
},
|
||||||
|
"queryAACube": {
|
||||||
|
"scale": 11.681488037109375,
|
||||||
|
"x": 0.25303030014038086,
|
||||||
|
"y": -4.834141254425049,
|
||||||
|
"z": -0.5721673965454102
|
||||||
|
},
|
||||||
|
"rotation": {
|
||||||
|
"w": 0.9662165641784668,
|
||||||
|
"x": -4.57763671875e-05,
|
||||||
|
"y": -0.2576791048049927,
|
||||||
|
"z": 1.52587890625e-05
|
||||||
|
},
|
||||||
|
"shape": "Cube",
|
||||||
|
"type": "Box",
|
||||||
|
"userData": "{\"grabbableKey\":{\"grabbable\":false}}",
|
||||||
|
"visible": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"clientOnly": false,
|
||||||
|
"created": "2018-09-05T00:40:03Z",
|
||||||
|
"dimensions": {
|
||||||
|
"blue": 14.40000057220459,
|
||||||
|
"green": 14.40000057220459,
|
||||||
|
"red": 14.40000057220459,
|
||||||
|
"x": 14.40000057220459,
|
||||||
|
"y": 14.40000057220459,
|
||||||
|
"z": 14.40000057220459
|
||||||
|
},
|
||||||
|
"id": "{baf96345-8f68-4068-af4c-3c690035852a}",
|
||||||
|
"lastEdited": 1536107948775591,
|
||||||
|
"lastEditedBy": "{b5bba536-25e5-4b12-a1be-5c7cd196a06a}",
|
||||||
|
"locked": true,
|
||||||
|
"owningAvatarID": "{00000000-0000-0000-0000-000000000000}",
|
||||||
|
"position": {
|
||||||
|
"blue": 2.3440732955932617,
|
||||||
|
"green": 1.6162219047546387,
|
||||||
|
"red": 1.8748211860656738,
|
||||||
|
"x": 1.8748211860656738,
|
||||||
|
"y": 1.6162219047546387,
|
||||||
|
"z": 2.3440732955932617
|
||||||
|
},
|
||||||
|
"queryAACube": {
|
||||||
|
"scale": 24.9415340423584,
|
||||||
|
"x": -10.595945358276367,
|
||||||
|
"y": -10.854545593261719,
|
||||||
|
"z": -10.126693725585938
|
||||||
|
},
|
||||||
|
"rotation": {
|
||||||
|
"w": 0.8697794675827026,
|
||||||
|
"x": -1.52587890625e-05,
|
||||||
|
"y": 0.4933699369430542,
|
||||||
|
"z": -4.57763671875e-05
|
||||||
|
},
|
||||||
|
"shapeType": "box",
|
||||||
|
"skyboxMode": "enabled",
|
||||||
|
"type": "Zone",
|
||||||
|
"userData": "{\"grabbableKey\":{\"grabbable\":false}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alpha": 0,
|
||||||
|
"alphaFinish": 0,
|
||||||
|
"alphaStart": 1,
|
||||||
|
"clientOnly": false,
|
||||||
|
"color": {
|
||||||
|
"blue": 211,
|
||||||
|
"green": 227,
|
||||||
|
"red": 104
|
||||||
|
},
|
||||||
|
"colorFinish": {
|
||||||
|
"blue": 0,
|
||||||
|
"green": 0,
|
||||||
|
"red": 0,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"colorStart": {
|
||||||
|
"blue": 211,
|
||||||
|
"green": 227,
|
||||||
|
"red": 104,
|
||||||
|
"x": 104,
|
||||||
|
"y": 227,
|
||||||
|
"z": 211
|
||||||
|
},
|
||||||
|
"created": "2018-09-05T00:40:03Z",
|
||||||
|
"dimensions": {
|
||||||
|
"blue": 2.5,
|
||||||
|
"green": 2.5,
|
||||||
|
"red": 2.5,
|
||||||
|
"x": 2.5,
|
||||||
|
"y": 2.5,
|
||||||
|
"z": 2.5
|
||||||
|
},
|
||||||
|
"emitAcceleration": {
|
||||||
|
"blue": 0,
|
||||||
|
"green": 0,
|
||||||
|
"red": 0,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"emitDimensions": {
|
||||||
|
"blue": 1,
|
||||||
|
"green": 1,
|
||||||
|
"red": 1,
|
||||||
|
"x": 1,
|
||||||
|
"y": 1,
|
||||||
|
"z": 1
|
||||||
|
},
|
||||||
|
"emitOrientation": {
|
||||||
|
"w": 0.9993909597396851,
|
||||||
|
"x": 0.034897372126579285,
|
||||||
|
"y": -1.525880907138344e-05,
|
||||||
|
"z": -1.525880907138344e-05
|
||||||
|
},
|
||||||
|
"emitRate": 2,
|
||||||
|
"emitSpeed": 0,
|
||||||
|
"id": "{639a51f0-8613-4e46-bc7e-fef24597df73}",
|
||||||
|
"lastEdited": 1536107948776693,
|
||||||
|
"lastEditedBy": "{b5bba536-25e5-4b12-a1be-5c7cd196a06a}",
|
||||||
|
"lifespan": 10,
|
||||||
|
"locked": true,
|
||||||
|
"maxParticles": 40,
|
||||||
|
"name": "Rays",
|
||||||
|
"owningAvatarID": "{00000000-0000-0000-0000-000000000000}",
|
||||||
|
"particleRadius": 0.75,
|
||||||
|
"polarFinish": 3.1415927410125732,
|
||||||
|
"position": {
|
||||||
|
"blue": 1.3553659915924072,
|
||||||
|
"green": 1.2890124320983887,
|
||||||
|
"red": 2.5663273334503174,
|
||||||
|
"x": 2.5663273334503174,
|
||||||
|
"y": 1.2890124320983887,
|
||||||
|
"z": 1.3553659915924072
|
||||||
|
},
|
||||||
|
"queryAACube": {
|
||||||
|
"scale": 4.330127239227295,
|
||||||
|
"x": 0.4012637138366699,
|
||||||
|
"y": -0.8760511875152588,
|
||||||
|
"z": -0.8096976280212402
|
||||||
|
},
|
||||||
|
"radiusFinish": 0.10000000149011612,
|
||||||
|
"radiusStart": 0,
|
||||||
|
"rotation": {
|
||||||
|
"w": 0.9803768396377563,
|
||||||
|
"x": -1.52587890625e-05,
|
||||||
|
"y": 0.19707024097442627,
|
||||||
|
"z": -7.62939453125e-05
|
||||||
|
},
|
||||||
|
"speedSpread": 0,
|
||||||
|
"spinFinish": null,
|
||||||
|
"spinStart": null,
|
||||||
|
"textures": "http://hifi-content.s3.amazonaws.com/alexia/Models/Portal/stripe.png",
|
||||||
|
"type": "ParticleEffect",
|
||||||
|
"userData": "{\"grabbableKey\":{\"grabbable\":false}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alpha": 0,
|
||||||
|
"alphaFinish": 0,
|
||||||
|
"alphaStart": 1,
|
||||||
|
"clientOnly": false,
|
||||||
|
"color": {
|
||||||
|
"blue": 255,
|
||||||
|
"green": 205,
|
||||||
|
"red": 3
|
||||||
|
},
|
||||||
|
"colorFinish": {
|
||||||
|
"blue": 0,
|
||||||
|
"green": 0,
|
||||||
|
"red": 0,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"colorStart": {
|
||||||
|
"blue": 255,
|
||||||
|
"green": 204,
|
||||||
|
"red": 0,
|
||||||
|
"x": 0,
|
||||||
|
"y": 204,
|
||||||
|
"z": 255
|
||||||
|
},
|
||||||
|
"created": "2018-09-05T00:40:03Z",
|
||||||
|
"dimensions": {
|
||||||
|
"blue": 2.5,
|
||||||
|
"green": 2.5,
|
||||||
|
"red": 2.5,
|
||||||
|
"x": 2.5,
|
||||||
|
"y": 2.5,
|
||||||
|
"z": 2.5
|
||||||
|
},
|
||||||
|
"emitAcceleration": {
|
||||||
|
"blue": 0,
|
||||||
|
"green": 0,
|
||||||
|
"red": 0,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"emitDimensions": {
|
||||||
|
"blue": 1,
|
||||||
|
"green": 1,
|
||||||
|
"red": 1,
|
||||||
|
"x": 1,
|
||||||
|
"y": 1,
|
||||||
|
"z": 1
|
||||||
|
},
|
||||||
|
"emitOrientation": {
|
||||||
|
"w": 0.9993909597396851,
|
||||||
|
"x": 0.034897372126579285,
|
||||||
|
"y": -1.525880907138344e-05,
|
||||||
|
"z": -1.525880907138344e-05
|
||||||
|
},
|
||||||
|
"emitRate": 2,
|
||||||
|
"emitSpeed": 0,
|
||||||
|
"emitterShouldTrail": true,
|
||||||
|
"id": "{e62ced49-fa18-4ae1-977f-abef5bc0f3ba}",
|
||||||
|
"lastEdited": 1536107948775366,
|
||||||
|
"lastEditedBy": "{b5bba536-25e5-4b12-a1be-5c7cd196a06a}",
|
||||||
|
"lifespan": 10,
|
||||||
|
"locked": true,
|
||||||
|
"maxParticles": 40,
|
||||||
|
"name": "Rays",
|
||||||
|
"owningAvatarID": "{00000000-0000-0000-0000-000000000000}",
|
||||||
|
"particleRadius": 0.75,
|
||||||
|
"polarFinish": 3.1415927410125732,
|
||||||
|
"position": {
|
||||||
|
"blue": 3.814434051513672,
|
||||||
|
"green": 1.2890124320983887,
|
||||||
|
"red": 1.2254328727722168,
|
||||||
|
"x": 1.2254328727722168,
|
||||||
|
"y": 1.2890124320983887,
|
||||||
|
"z": 3.814434051513672
|
||||||
|
},
|
||||||
|
"queryAACube": {
|
||||||
|
"scale": 4.330127239227295,
|
||||||
|
"x": -0.9396307468414307,
|
||||||
|
"y": -0.8760511875152588,
|
||||||
|
"z": 1.6493704319000244
|
||||||
|
},
|
||||||
|
"radiusFinish": 0.10000000149011612,
|
||||||
|
"radiusStart": 0,
|
||||||
|
"rotation": {
|
||||||
|
"w": 0.9594720602035522,
|
||||||
|
"x": -1.52587890625e-05,
|
||||||
|
"y": 0.28178834915161133,
|
||||||
|
"z": -4.57763671875e-05
|
||||||
|
},
|
||||||
|
"speedSpread": 0,
|
||||||
|
"spinFinish": null,
|
||||||
|
"spinStart": null,
|
||||||
|
"textures": "http://hifi-content.s3.amazonaws.com/alexia/Models/Portal/stripe.png",
|
||||||
|
"type": "ParticleEffect",
|
||||||
|
"userData": "{\"grabbableKey\":{\"grabbable\":false}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alpha": 0,
|
||||||
|
"alphaFinish": 0,
|
||||||
|
"alphaStart": 0.25,
|
||||||
|
"clientOnly": false,
|
||||||
|
"colorFinish": {
|
||||||
|
"blue": 0,
|
||||||
|
"green": 0,
|
||||||
|
"red": 0,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"colorStart": {
|
||||||
|
"blue": 255,
|
||||||
|
"green": 255,
|
||||||
|
"red": 255,
|
||||||
|
"x": 255,
|
||||||
|
"y": 255,
|
||||||
|
"z": 255
|
||||||
|
},
|
||||||
|
"created": "2018-09-05T00:40:03Z",
|
||||||
|
"dimensions": {
|
||||||
|
"blue": 13.24000072479248,
|
||||||
|
"green": 13.24000072479248,
|
||||||
|
"red": 13.24000072479248,
|
||||||
|
"x": 13.24000072479248,
|
||||||
|
"y": 13.24000072479248,
|
||||||
|
"z": 13.24000072479248
|
||||||
|
},
|
||||||
|
"emitAcceleration": {
|
||||||
|
"blue": 0,
|
||||||
|
"green": 0.10000000149011612,
|
||||||
|
"red": 0,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0.10000000149011612,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"emitDimensions": {
|
||||||
|
"blue": 1,
|
||||||
|
"green": 1,
|
||||||
|
"red": 1,
|
||||||
|
"x": 1,
|
||||||
|
"y": 1,
|
||||||
|
"z": 1
|
||||||
|
},
|
||||||
|
"emitOrientation": {
|
||||||
|
"w": 1,
|
||||||
|
"x": -1.52587890625e-05,
|
||||||
|
"y": -1.52587890625e-05,
|
||||||
|
"z": -1.52587890625e-05
|
||||||
|
},
|
||||||
|
"emitRate": 6,
|
||||||
|
"emitSpeed": 0,
|
||||||
|
"id": "{298c0571-cbd8-487b-8640-64037d6a8414}",
|
||||||
|
"lastEdited": 1536107948776382,
|
||||||
|
"lastEditedBy": "{b5bba536-25e5-4b12-a1be-5c7cd196a06a}",
|
||||||
|
"lifespan": 10,
|
||||||
|
"locked": true,
|
||||||
|
"maxParticles": 10,
|
||||||
|
"name": "Stars",
|
||||||
|
"owningAvatarID": "{00000000-0000-0000-0000-000000000000}",
|
||||||
|
"particleRadius": 0.07000000029802322,
|
||||||
|
"polarFinish": 3.1415927410125732,
|
||||||
|
"position": {
|
||||||
|
"blue": 1.3712034225463867,
|
||||||
|
"green": 0.3698839843273163,
|
||||||
|
"red": 2.6216418743133545,
|
||||||
|
"x": 2.6216418743133545,
|
||||||
|
"y": 0.3698839843273163,
|
||||||
|
"z": 1.3712034225463867
|
||||||
|
},
|
||||||
|
"queryAACube": {
|
||||||
|
"scale": 22.932353973388672,
|
||||||
|
"x": -8.844534873962402,
|
||||||
|
"y": -11.096293449401855,
|
||||||
|
"z": -10.09497356414795
|
||||||
|
},
|
||||||
|
"radiusFinish": 0,
|
||||||
|
"radiusStart": 0,
|
||||||
|
"rotation": {
|
||||||
|
"w": 0.9852597713470459,
|
||||||
|
"x": -1.52587890625e-05,
|
||||||
|
"y": -0.17106890678405762,
|
||||||
|
"z": -7.62939453125e-05
|
||||||
|
},
|
||||||
|
"speedSpread": 0,
|
||||||
|
"spinFinish": null,
|
||||||
|
"spinStart": null,
|
||||||
|
"textures": "http://hifi-content.s3.amazonaws.com/alexia/Models/Portal/star.png",
|
||||||
|
"type": "ParticleEffect",
|
||||||
|
"userData": "{\"grabbableKey\":{\"grabbable\":false}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"clientOnly": false,
|
||||||
|
"created": "2018-09-05T00:40:03Z",
|
||||||
|
"dimensions": {
|
||||||
|
"blue": 2.1097896099090576,
|
||||||
|
"green": 0.04847164824604988,
|
||||||
|
"red": 1.458284616470337,
|
||||||
|
"x": 1.458284616470337,
|
||||||
|
"y": 0.04847164824604988,
|
||||||
|
"z": 2.1097896099090576
|
||||||
|
},
|
||||||
|
"id": "{6625dbb8-ff25-458d-a92e-644b58460604}",
|
||||||
|
"lastEdited": 1536107948776195,
|
||||||
|
"lastEditedBy": "{b5bba536-25e5-4b12-a1be-5c7cd196a06a}",
|
||||||
|
"locked": true,
|
||||||
|
"modelURL": "http://hifi-content.s3.amazonaws.com/alexia/Models/Portal/portal1.fbx",
|
||||||
|
"name": "Try Again",
|
||||||
|
"owningAvatarID": "{00000000-0000-0000-0000-000000000000}",
|
||||||
|
"position": {
|
||||||
|
"blue": 3.946338653564453,
|
||||||
|
"green": 0.09449335932731628,
|
||||||
|
"red": 1.594836711883545,
|
||||||
|
"x": 1.594836711883545,
|
||||||
|
"y": 0.09449335932731628,
|
||||||
|
"z": 3.946338653564453
|
||||||
|
},
|
||||||
|
"queryAACube": {
|
||||||
|
"scale": 2.5651814937591553,
|
||||||
|
"x": 0.3122459650039673,
|
||||||
|
"y": -1.188097357749939,
|
||||||
|
"z": 2.663747787475586
|
||||||
|
},
|
||||||
|
"rotation": {
|
||||||
|
"w": 0.8220492601394653,
|
||||||
|
"x": -1.52587890625e-05,
|
||||||
|
"y": 0.5693598985671997,
|
||||||
|
"z": -0.0001068115234375
|
||||||
|
},
|
||||||
|
"script": "https://hifi-content.s3.amazonaws.com/wayne/404redirectionScripts/tryAgainEntityScript.js",
|
||||||
|
"shapeType": "static-mesh",
|
||||||
|
"type": "Model",
|
||||||
|
"userData": "{\"grabbableKey\":{\"grabbable\":false}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"clientOnly": false,
|
||||||
|
"created": "2018-09-05T00:40:03Z",
|
||||||
|
"dimensions": {
|
||||||
|
"blue": 0.06014331430196762,
|
||||||
|
"green": 2.582186460494995,
|
||||||
|
"red": 2.582186698913574,
|
||||||
|
"x": 2.582186698913574,
|
||||||
|
"y": 2.582186460494995,
|
||||||
|
"z": 0.06014331430196762
|
||||||
|
},
|
||||||
|
"id": "{dfe92dce-f09d-4e9e-b3ed-c68ecd4d476f}",
|
||||||
|
"lastEdited": 1536108160862286,
|
||||||
|
"lastEditedBy": "{4656d4a8-5e61-4230-ab34-2888d7945bd6}",
|
||||||
|
"modelURL": "",
|
||||||
|
"name": "Oops Dialog",
|
||||||
|
"owningAvatarID": "{00000000-0000-0000-0000-000000000000}",
|
||||||
|
"position": {
|
||||||
|
"blue": 1.45927095413208,
|
||||||
|
"green": 1.6763916015625,
|
||||||
|
"red": 0,
|
||||||
|
"x": 0,
|
||||||
|
"y": 1.6763916015625,
|
||||||
|
"z": 1.45927095413208
|
||||||
|
},
|
||||||
|
"queryAACube": {
|
||||||
|
"scale": 3.6522583961486816,
|
||||||
|
"x": -1.8261291980743408,
|
||||||
|
"y": -0.14973759651184082,
|
||||||
|
"z": -0.36685824394226074
|
||||||
|
},
|
||||||
|
"rotation": {
|
||||||
|
"w": 0.8684672117233276,
|
||||||
|
"x": -4.57763671875e-05,
|
||||||
|
"y": 0.4957197904586792,
|
||||||
|
"z": -7.62939453125e-05
|
||||||
|
},
|
||||||
|
"script": "https://hifi-content.s3.amazonaws.com/wayne/404redirectionScripts/oopsEntityScript.js",
|
||||||
|
"scriptTimestamp": 1536102551825,
|
||||||
|
"type": "Model",
|
||||||
|
"userData": "{\"grabbableKey\":{\"grabbable\":false}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"clientOnly": false,
|
||||||
|
"color": {
|
||||||
|
"blue": 0,
|
||||||
|
"green": 0,
|
||||||
|
"red": 0
|
||||||
|
},
|
||||||
|
"created": "2018-09-05T00:40:03Z",
|
||||||
|
"dimensions": {
|
||||||
|
"blue": 11.117486953735352,
|
||||||
|
"green": 3.580313205718994,
|
||||||
|
"red": 0.20000000298023224,
|
||||||
|
"x": 0.20000000298023224,
|
||||||
|
"y": 3.580313205718994,
|
||||||
|
"z": 11.117486953735352
|
||||||
|
},
|
||||||
|
"id": "{144a8cf4-b0e8-489a-9403-d74d4dc4cb3e}",
|
||||||
|
"lastEdited": 1536107948775774,
|
||||||
|
"lastEditedBy": "{ce82d352-3002-44ae-9b76-66492989a1db}",
|
||||||
|
"locked": true,
|
||||||
|
"name": "rightWall",
|
||||||
|
"owningAvatarID": "{00000000-0000-0000-0000-000000000000}",
|
||||||
|
"position": {
|
||||||
|
"blue": 0,
|
||||||
|
"green": 1.0061144828796387,
|
||||||
|
"red": 4.965089321136475,
|
||||||
|
"x": 4.965089321136475,
|
||||||
|
"y": 1.0061144828796387,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"queryAACube": {
|
||||||
|
"scale": 11.681488037109375,
|
||||||
|
"x": -0.8756546974182129,
|
||||||
|
"y": -4.834629535675049,
|
||||||
|
"z": -5.8407440185546875
|
||||||
|
},
|
||||||
|
"rotation": {
|
||||||
|
"w": 0.8637980222702026,
|
||||||
|
"x": -4.57763671875e-05,
|
||||||
|
"y": 0.5038070678710938,
|
||||||
|
"z": -1.52587890625e-05
|
||||||
|
},
|
||||||
|
"shape": "Cube",
|
||||||
|
"type": "Box",
|
||||||
|
"userData": "{\"grabbableKey\":{\"grabbable\":false}}",
|
||||||
|
"visible": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"clientOnly": false,
|
||||||
|
"collidesWith": "static,dynamic,kinematic,otherAvatar,",
|
||||||
|
"collisionMask": 23,
|
||||||
|
"created": "2018-09-05T00:40:03Z",
|
||||||
|
"dimensions": {
|
||||||
|
"blue": 1.159199833869934,
|
||||||
|
"green": 2.8062009811401367,
|
||||||
|
"red": 1.6216505765914917,
|
||||||
|
"x": 1.6216505765914917,
|
||||||
|
"y": 2.8062009811401367,
|
||||||
|
"z": 1.159199833869934
|
||||||
|
},
|
||||||
|
"id": "{37f53408-3d0c-42a5-9891-e6c40a227349}",
|
||||||
|
"lastEdited": 1536107948775010,
|
||||||
|
"lastEditedBy": "{b5bba536-25e5-4b12-a1be-5c7cd196a06a}",
|
||||||
|
"locked": true,
|
||||||
|
"name": "Back Zone",
|
||||||
|
"owningAvatarID": "{00000000-0000-0000-0000-000000000000}",
|
||||||
|
"position": {
|
||||||
|
"blue": 1.8632707595825195,
|
||||||
|
"green": 1.6500625610351562,
|
||||||
|
"red": 3.3211965560913086,
|
||||||
|
"x": 3.3211965560913086,
|
||||||
|
"y": 1.6500625610351562,
|
||||||
|
"z": 1.8632707595825195
|
||||||
|
},
|
||||||
|
"queryAACube": {
|
||||||
|
"scale": 3.4421300888061523,
|
||||||
|
"x": 1.6001315116882324,
|
||||||
|
"y": -0.07100248336791992,
|
||||||
|
"z": 0.14220571517944336
|
||||||
|
},
|
||||||
|
"rotation": {
|
||||||
|
"w": 0.9304176568984985,
|
||||||
|
"x": 0,
|
||||||
|
"y": -0.36650121212005615,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"script": "https://hifi-content.s3.amazonaws.com/wayne/404redirectionScripts/zoneBackEntityScript.js",
|
||||||
|
"shapeType": "box",
|
||||||
|
"type": "Zone",
|
||||||
|
"userData": "{\"grabbableKey\":{\"grabbable\":false}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"clientOnly": false,
|
||||||
|
"color": {
|
||||||
|
"blue": 0,
|
||||||
|
"green": 0,
|
||||||
|
"red": 0
|
||||||
|
},
|
||||||
|
"created": "2018-09-05T00:40:03Z",
|
||||||
|
"dimensions": {
|
||||||
|
"blue": 11.117486953735352,
|
||||||
|
"green": 3.580313205718994,
|
||||||
|
"red": 0.20000000298023224,
|
||||||
|
"x": 0.20000000298023224,
|
||||||
|
"y": 3.580313205718994,
|
||||||
|
"z": 11.117486953735352
|
||||||
|
},
|
||||||
|
"id": "{aa6e680c-6750-4776-95bc-ef3118cace5c}",
|
||||||
|
"lastEdited": 1536107948775945,
|
||||||
|
"lastEditedBy": "{ce82d352-3002-44ae-9b76-66492989a1db}",
|
||||||
|
"locked": true,
|
||||||
|
"name": "frontWall",
|
||||||
|
"owningAvatarID": "{00000000-0000-0000-0000-000000000000}",
|
||||||
|
"position": {
|
||||||
|
"blue": 2.662257671356201,
|
||||||
|
"green": 1.0063786506652832,
|
||||||
|
"red": 1.4868733882904053,
|
||||||
|
"x": 1.4868733882904053,
|
||||||
|
"y": 1.0063786506652832,
|
||||||
|
"z": 2.662257671356201
|
||||||
|
},
|
||||||
|
"queryAACube": {
|
||||||
|
"scale": 11.681488037109375,
|
||||||
|
"x": -4.353870391845703,
|
||||||
|
"y": -4.834365367889404,
|
||||||
|
"z": -3.1784863471984863
|
||||||
|
},
|
||||||
|
"rotation": {
|
||||||
|
"w": 0.9666743278503418,
|
||||||
|
"x": -4.57763671875e-05,
|
||||||
|
"y": -0.2560006380081177,
|
||||||
|
"z": 1.52587890625e-05
|
||||||
|
},
|
||||||
|
"shape": "Cube",
|
||||||
|
"type": "Box",
|
||||||
|
"userData": "{\"grabbableKey\":{\"grabbable\":false}}",
|
||||||
|
"visible": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"clientOnly": false,
|
||||||
|
"created": "2018-09-05T00:40:03Z",
|
||||||
|
"dimensions": {
|
||||||
|
"blue": 2.1097896099090576,
|
||||||
|
"green": 0.04847164824604988,
|
||||||
|
"red": 1.458284616470337,
|
||||||
|
"x": 1.458284616470337,
|
||||||
|
"y": 0.04847164824604988,
|
||||||
|
"z": 2.1097896099090576
|
||||||
|
},
|
||||||
|
"id": "{303631f1-04f3-42a6-b8a8-8dd4b65d1231}",
|
||||||
|
"lastEdited": 1536107948776513,
|
||||||
|
"lastEditedBy": "{b5bba536-25e5-4b12-a1be-5c7cd196a06a}",
|
||||||
|
"locked": true,
|
||||||
|
"modelURL": "http://hifi-content.s3.amazonaws.com/alexia/Models/Portal/portal2.fbx",
|
||||||
|
"name": "Back",
|
||||||
|
"owningAvatarID": "{00000000-0000-0000-0000-000000000000}",
|
||||||
|
"position": {
|
||||||
|
"blue": 1.5835940837860107,
|
||||||
|
"green": 0.09449335932731628,
|
||||||
|
"red": 3.028078079223633,
|
||||||
|
"x": 3.028078079223633,
|
||||||
|
"y": 0.09449335932731628,
|
||||||
|
"z": 1.5835940837860107
|
||||||
|
},
|
||||||
|
"queryAACube": {
|
||||||
|
"scale": 2.5651814937591553,
|
||||||
|
"x": 1.7454873323440552,
|
||||||
|
"y": -1.188097357749939,
|
||||||
|
"z": 0.3010033369064331
|
||||||
|
},
|
||||||
|
"rotation": {
|
||||||
|
"w": 0.9084458351135254,
|
||||||
|
"x": -1.52587890625e-05,
|
||||||
|
"y": 0.4179598093032837,
|
||||||
|
"z": -0.0001068115234375
|
||||||
|
},
|
||||||
|
"script": "https://hifi-content.s3.amazonaws.com/wayne/404redirectionScripts/backEntityScript.js",
|
||||||
|
"scriptTimestamp": 1535751754379,
|
||||||
|
"shapeType": "static-mesh",
|
||||||
|
"type": "Model",
|
||||||
|
"userData": "{\"grabbableKey\":{\"grabbable\":false}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alpha": 0,
|
||||||
|
"alphaFinish": 0,
|
||||||
|
"alphaStart": 0.25,
|
||||||
|
"clientOnly": false,
|
||||||
|
"colorFinish": {
|
||||||
|
"blue": 0,
|
||||||
|
"green": 0,
|
||||||
|
"red": 0,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"colorStart": {
|
||||||
|
"blue": 255,
|
||||||
|
"green": 255,
|
||||||
|
"red": 255,
|
||||||
|
"x": 255,
|
||||||
|
"y": 255,
|
||||||
|
"z": 255
|
||||||
|
},
|
||||||
|
"created": "2018-09-05T00:40:03Z",
|
||||||
|
"dimensions": {
|
||||||
|
"blue": 13.24000072479248,
|
||||||
|
"green": 13.24000072479248,
|
||||||
|
"red": 13.24000072479248,
|
||||||
|
"x": 13.24000072479248,
|
||||||
|
"y": 13.24000072479248,
|
||||||
|
"z": 13.24000072479248
|
||||||
|
},
|
||||||
|
"emitAcceleration": {
|
||||||
|
"blue": 0,
|
||||||
|
"green": 0.10000000149011612,
|
||||||
|
"red": 0,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0.10000000149011612,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"emitDimensions": {
|
||||||
|
"blue": 1,
|
||||||
|
"green": 1,
|
||||||
|
"red": 1,
|
||||||
|
"x": 1,
|
||||||
|
"y": 1,
|
||||||
|
"z": 1
|
||||||
|
},
|
||||||
|
"emitOrientation": {
|
||||||
|
"w": 1,
|
||||||
|
"x": -1.52587890625e-05,
|
||||||
|
"y": -1.52587890625e-05,
|
||||||
|
"z": -1.52587890625e-05
|
||||||
|
},
|
||||||
|
"emitRate": 6,
|
||||||
|
"emitSpeed": 0,
|
||||||
|
"emitterShouldTrail": true,
|
||||||
|
"id": "{8ded39e6-303c-48f2-be79-81b715cca9f7}",
|
||||||
|
"lastEdited": 1536107948777127,
|
||||||
|
"lastEditedBy": "{b5bba536-25e5-4b12-a1be-5c7cd196a06a}",
|
||||||
|
"lifespan": 10,
|
||||||
|
"locked": true,
|
||||||
|
"maxParticles": 10,
|
||||||
|
"name": "Stars",
|
||||||
|
"owningAvatarID": "{00000000-0000-0000-0000-000000000000}",
|
||||||
|
"particleRadius": 0.07000000029802322,
|
||||||
|
"polarFinish": 3.1415927410125732,
|
||||||
|
"position": {
|
||||||
|
"blue": 3.78922963142395,
|
||||||
|
"green": 0.3698839843273163,
|
||||||
|
"red": 1.1863799095153809,
|
||||||
|
"x": 1.1863799095153809,
|
||||||
|
"y": 0.3698839843273163,
|
||||||
|
"z": 3.78922963142395
|
||||||
|
},
|
||||||
|
"queryAACube": {
|
||||||
|
"scale": 22.932353973388672,
|
||||||
|
"x": -10.279796600341797,
|
||||||
|
"y": -11.096293449401855,
|
||||||
|
"z": -7.676947593688965
|
||||||
|
},
|
||||||
|
"radiusFinish": 0,
|
||||||
|
"radiusStart": 0,
|
||||||
|
"rotation": {
|
||||||
|
"w": 0.996429443359375,
|
||||||
|
"x": -1.52587890625e-05,
|
||||||
|
"y": -0.08442819118499756,
|
||||||
|
"z": -4.57763671875e-05
|
||||||
|
},
|
||||||
|
"speedSpread": 0,
|
||||||
|
"spinFinish": null,
|
||||||
|
"spinStart": null,
|
||||||
|
"textures": "http://hifi-content.s3.amazonaws.com/alexia/Models/Portal/star.png",
|
||||||
|
"type": "ParticleEffect",
|
||||||
|
"userData": "{\"grabbableKey\":{\"grabbable\":false}}"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Id": "{18abccad-2d57-4176-9d89-24dc424916f5}",
|
||||||
|
"Version": 93
|
||||||
|
}
|
|
@ -1186,13 +1186,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
const DomainHandler& domainHandler = nodeList->getDomainHandler();
|
const DomainHandler& domainHandler = nodeList->getDomainHandler();
|
||||||
|
|
||||||
connect(&domainHandler, SIGNAL(domainURLChanged(QUrl)), SLOT(domainURLChanged(QUrl)));
|
connect(&domainHandler, SIGNAL(domainURLChanged(QUrl)), SLOT(domainURLChanged(QUrl)));
|
||||||
|
connect(&domainHandler, SIGNAL(redirectToErrorDomainURL(QUrl)), SLOT(goToErrorDomainURL(QUrl)));
|
||||||
connect(&domainHandler, &DomainHandler::domainURLChanged, [](QUrl domainURL){
|
connect(&domainHandler, &DomainHandler::domainURLChanged, [](QUrl domainURL){
|
||||||
setCrashAnnotation("domain", domainURL.toString().toStdString());
|
setCrashAnnotation("domain", domainURL.toString().toStdString());
|
||||||
});
|
});
|
||||||
connect(&domainHandler, SIGNAL(resetting()), SLOT(resettingDomain()));
|
connect(&domainHandler, SIGNAL(resetting()), SLOT(resettingDomain()));
|
||||||
connect(&domainHandler, SIGNAL(connectedToDomain(QUrl)), SLOT(updateWindowTitle()));
|
connect(&domainHandler, SIGNAL(connectedToDomain(QUrl)), SLOT(updateWindowTitle()));
|
||||||
connect(&domainHandler, SIGNAL(disconnectedFromDomain()), SLOT(updateWindowTitle()));
|
connect(&domainHandler, SIGNAL(disconnectedFromDomain()), SLOT(updateWindowTitle()));
|
||||||
connect(&domainHandler, &DomainHandler::disconnectedFromDomain, this, &Application::clearDomainAvatars);
|
|
||||||
connect(&domainHandler, &DomainHandler::disconnectedFromDomain, this, [this]() {
|
connect(&domainHandler, &DomainHandler::disconnectedFromDomain, this, [this]() {
|
||||||
getOverlays().deleteOverlay(getTabletScreenID());
|
getOverlays().deleteOverlay(getTabletScreenID());
|
||||||
getOverlays().deleteOverlay(getTabletHomeButtonID());
|
getOverlays().deleteOverlay(getTabletHomeButtonID());
|
||||||
|
@ -1200,6 +1200,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
});
|
});
|
||||||
connect(&domainHandler, &DomainHandler::domainConnectionRefused, this, &Application::domainConnectionRefused);
|
connect(&domainHandler, &DomainHandler::domainConnectionRefused, this, &Application::domainConnectionRefused);
|
||||||
|
|
||||||
|
nodeList->getDomainHandler().setErrorDomainURL(QUrl(REDIRECT_HIFI_ADDRESS));
|
||||||
|
|
||||||
// We could clear ATP assets only when changing domains, but it's possible that the domain you are connected
|
// We could clear ATP assets only when changing domains, but it's possible that the domain you are connected
|
||||||
// to has gone down and switched to a new content set, so when you reconnect the cached ATP assets will no longer be valid.
|
// to has gone down and switched to a new content set, so when you reconnect the cached ATP assets will no longer be valid.
|
||||||
connect(&domainHandler, &DomainHandler::disconnectedFromDomain, DependencyManager::get<ScriptCache>().data(), &ScriptCache::clearATPScriptsFromCache);
|
connect(&domainHandler, &DomainHandler::disconnectedFromDomain, DependencyManager::get<ScriptCache>().data(), &ScriptCache::clearATPScriptsFromCache);
|
||||||
|
@ -1641,7 +1643,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
audioClient->setMuted(!audioClient->isMuted());
|
audioClient->setMuted(!audioClient->isMuted());
|
||||||
} else if (action == controller::toInt(controller::Action::CYCLE_CAMERA)) {
|
} else if (action == controller::toInt(controller::Action::CYCLE_CAMERA)) {
|
||||||
cycleCamera();
|
cycleCamera();
|
||||||
} else if (action == controller::toInt(controller::Action::CONTEXT_MENU)) {
|
} else if (action == controller::toInt(controller::Action::CONTEXT_MENU) && !isInterstitialMode()) {
|
||||||
toggleTabletUI();
|
toggleTabletUI();
|
||||||
} else if (action == controller::toInt(controller::Action::RETICLE_X)) {
|
} else if (action == controller::toInt(controller::Action::RETICLE_X)) {
|
||||||
auto oldPos = getApplicationCompositor().getReticlePosition();
|
auto oldPos = getApplicationCompositor().getReticlePosition();
|
||||||
|
@ -2250,6 +2252,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
|
|
||||||
connect(this, &QCoreApplication::aboutToQuit, this, &Application::addAssetToWorldMessageClose);
|
connect(this, &QCoreApplication::aboutToQuit, this, &Application::addAssetToWorldMessageClose);
|
||||||
connect(&domainHandler, &DomainHandler::domainURLChanged, this, &Application::addAssetToWorldMessageClose);
|
connect(&domainHandler, &DomainHandler::domainURLChanged, this, &Application::addAssetToWorldMessageClose);
|
||||||
|
connect(&domainHandler, &DomainHandler::redirectToErrorDomainURL, this, &Application::addAssetToWorldMessageClose);
|
||||||
|
|
||||||
updateSystemTabletMode();
|
updateSystemTabletMode();
|
||||||
|
|
||||||
|
@ -2300,6 +2303,24 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
connect(&AndroidHelper::instance(), &AndroidHelper::enterForeground, this, &Application::enterForeground);
|
connect(&AndroidHelper::instance(), &AndroidHelper::enterForeground, this, &Application::enterForeground);
|
||||||
AndroidHelper::instance().notifyLoadComplete();
|
AndroidHelper::instance().notifyLoadComplete();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int CHECK_LOGIN_TIMER = 3000;
|
||||||
|
QTimer* checkLoginTimer = new QTimer(this);
|
||||||
|
checkLoginTimer->setInterval(CHECK_LOGIN_TIMER);
|
||||||
|
checkLoginTimer->setSingleShot(true);
|
||||||
|
connect(checkLoginTimer, &QTimer::timeout, this, [this]() {
|
||||||
|
auto accountManager = DependencyManager::get<AccountManager>();
|
||||||
|
auto dialogsManager = DependencyManager::get<DialogsManager>();
|
||||||
|
if (!accountManager->isLoggedIn()) {
|
||||||
|
Setting::Handle<bool>{"loginDialogPoppedUp", false}.set(true);
|
||||||
|
dialogsManager->showLoginDialog();
|
||||||
|
QJsonObject loginData = {};
|
||||||
|
loginData["action"] = "login dialog shown";
|
||||||
|
UserActivityLogger::getInstance().logAction("encourageLoginDialog", loginData);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Setting::Handle<bool>{"loginDialogPoppedUp", false}.set(false);
|
||||||
|
checkLoginTimer->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::updateVerboseLogging() {
|
void Application::updateVerboseLogging() {
|
||||||
|
@ -2433,6 +2454,8 @@ void Application::onAboutToQuit() {
|
||||||
// so its persisted explicitly here
|
// so its persisted explicitly here
|
||||||
Setting::Handle<QString>{ ACTIVE_DISPLAY_PLUGIN_SETTING_NAME }.set(getActiveDisplayPlugin()->getName());
|
Setting::Handle<QString>{ ACTIVE_DISPLAY_PLUGIN_SETTING_NAME }.set(getActiveDisplayPlugin()->getName());
|
||||||
|
|
||||||
|
Setting::Handle<bool>{"loginDialogPoppedUp", false}.set(false);
|
||||||
|
|
||||||
getActiveDisplayPlugin()->deactivate();
|
getActiveDisplayPlugin()->deactivate();
|
||||||
if (_autoSwitchDisplayModeSupportedHMDPlugin
|
if (_autoSwitchDisplayModeSupportedHMDPlugin
|
||||||
&& _autoSwitchDisplayModeSupportedHMDPlugin->isSessionActive()) {
|
&& _autoSwitchDisplayModeSupportedHMDPlugin->isSessionActive()) {
|
||||||
|
@ -2993,6 +3016,9 @@ void Application::initializeUi() {
|
||||||
if (_window && _window->isFullScreen()) {
|
if (_window && _window->isFullScreen()) {
|
||||||
setFullscreen(nullptr, true);
|
setFullscreen(nullptr, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
setIsInterstitialMode(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3471,6 +3497,15 @@ bool Application::isServerlessMode() const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::setIsInterstitialMode(bool interstitialMode) {
|
||||||
|
if (_interstitialMode != interstitialMode) {
|
||||||
|
_interstitialMode = interstitialMode;
|
||||||
|
|
||||||
|
DependencyManager::get<AudioClient>()->setAudioPaused(_interstitialMode);
|
||||||
|
DependencyManager::get<AvatarManager>()->setMyAvatarDataPacketsPaused(_interstitialMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Application::setIsServerlessMode(bool serverlessDomain) {
|
void Application::setIsServerlessMode(bool serverlessDomain) {
|
||||||
auto tree = getEntities()->getTree();
|
auto tree = getEntities()->getTree();
|
||||||
if (tree) {
|
if (tree) {
|
||||||
|
@ -3478,9 +3513,9 @@ void Application::setIsServerlessMode(bool serverlessDomain) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::loadServerlessDomain(QUrl domainURL) {
|
void Application::loadServerlessDomain(QUrl domainURL, bool errorDomain) {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QMetaObject::invokeMethod(this, "loadServerlessDomain", Q_ARG(QUrl, domainURL));
|
QMetaObject::invokeMethod(this, "loadServerlessDomain", Q_ARG(QUrl, domainURL), Q_ARG(bool, errorDomain));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3512,8 +3547,11 @@ void Application::loadServerlessDomain(QUrl domainURL) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<QString, QString> namedPaths = tmpTree->getNamedPaths();
|
std::map<QString, QString> namedPaths = tmpTree->getNamedPaths();
|
||||||
nodeList->getDomainHandler().connectedToServerless(namedPaths);
|
if (errorDomain) {
|
||||||
|
nodeList->getDomainHandler().loadedErrorDomain(namedPaths);
|
||||||
|
} else {
|
||||||
|
nodeList->getDomainHandler().connectedToServerless(namedPaths);
|
||||||
|
}
|
||||||
|
|
||||||
_fullSceneReceivedCounter++;
|
_fullSceneReceivedCounter++;
|
||||||
}
|
}
|
||||||
|
@ -3748,7 +3786,7 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
||||||
|
|
||||||
_controllerScriptingInterface->emitKeyPressEvent(event); // send events to any registered scripts
|
_controllerScriptingInterface->emitKeyPressEvent(event); // send events to any registered scripts
|
||||||
// if one of our scripts have asked to capture this event, then stop processing it
|
// if one of our scripts have asked to capture this event, then stop processing it
|
||||||
if (_controllerScriptingInterface->isKeyCaptured(event)) {
|
if (_controllerScriptingInterface->isKeyCaptured(event) || isInterstitialMode()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5535,6 +5573,7 @@ void Application::update(float deltaTime) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!_physicsEnabled) {
|
if (!_physicsEnabled) {
|
||||||
if (!domainLoadingInProgress) {
|
if (!domainLoadingInProgress) {
|
||||||
PROFILE_ASYNC_BEGIN(app, "Scene Loading", "");
|
PROFILE_ASYNC_BEGIN(app, "Scene Loading", "");
|
||||||
|
@ -5555,6 +5594,7 @@ void Application::update(float deltaTime) {
|
||||||
// scene is ready to compute its collision shape.
|
// scene is ready to compute its collision shape.
|
||||||
if (getMyAvatar()->isReadyForPhysics()) {
|
if (getMyAvatar()->isReadyForPhysics()) {
|
||||||
_physicsEnabled = true;
|
_physicsEnabled = true;
|
||||||
|
setIsInterstitialMode(false);
|
||||||
getMyAvatar()->updateMotionBehaviorFromMenu();
|
getMyAvatar()->updateMotionBehaviorFromMenu();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5634,7 +5674,7 @@ void Application::update(float deltaTime) {
|
||||||
// Transfer the user inputs to the driveKeys
|
// Transfer the user inputs to the driveKeys
|
||||||
// FIXME can we drop drive keys and just have the avatar read the action states directly?
|
// FIXME can we drop drive keys and just have the avatar read the action states directly?
|
||||||
myAvatar->clearDriveKeys();
|
myAvatar->clearDriveKeys();
|
||||||
if (_myCamera.getMode() != CAMERA_MODE_INDEPENDENT) {
|
if (_myCamera.getMode() != CAMERA_MODE_INDEPENDENT && !isInterstitialMode()) {
|
||||||
if (!_controllerScriptingInterface->areActionsCaptured() && _myCamera.getMode() != CAMERA_MODE_MIRROR) {
|
if (!_controllerScriptingInterface->areActionsCaptured() && _myCamera.getMode() != CAMERA_MODE_MIRROR) {
|
||||||
myAvatar->setDriveKey(MyAvatar::TRANSLATE_Z, -1.0f * userInputMapper->getActionState(controller::Action::TRANSLATE_Z));
|
myAvatar->setDriveKey(MyAvatar::TRANSLATE_Z, -1.0f * userInputMapper->getActionState(controller::Action::TRANSLATE_Z));
|
||||||
myAvatar->setDriveKey(MyAvatar::TRANSLATE_Y, userInputMapper->getActionState(controller::Action::TRANSLATE_Y));
|
myAvatar->setDriveKey(MyAvatar::TRANSLATE_Y, userInputMapper->getActionState(controller::Action::TRANSLATE_Y));
|
||||||
|
@ -5950,7 +5990,7 @@ void Application::update(float deltaTime) {
|
||||||
// send packet containing downstream audio stats to the AudioMixer
|
// send packet containing downstream audio stats to the AudioMixer
|
||||||
{
|
{
|
||||||
quint64 sinceLastNack = now - _lastSendDownstreamAudioStats;
|
quint64 sinceLastNack = now - _lastSendDownstreamAudioStats;
|
||||||
if (sinceLastNack > TOO_LONG_SINCE_LAST_SEND_DOWNSTREAM_AUDIO_STATS) {
|
if (sinceLastNack > TOO_LONG_SINCE_LAST_SEND_DOWNSTREAM_AUDIO_STATS && !isInterstitialMode()) {
|
||||||
_lastSendDownstreamAudioStats = now;
|
_lastSendDownstreamAudioStats = now;
|
||||||
|
|
||||||
QMetaObject::invokeMethod(DependencyManager::get<AudioClient>().data(), "sendDownstreamAudioStatsPacket", Qt::QueuedConnection);
|
QMetaObject::invokeMethod(DependencyManager::get<AudioClient>().data(), "sendDownstreamAudioStatsPacket", Qt::QueuedConnection);
|
||||||
|
@ -6113,21 +6153,23 @@ void Application::updateRenderArgs(float deltaTime) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::queryAvatars() {
|
void Application::queryAvatars() {
|
||||||
auto avatarPacket = NLPacket::create(PacketType::AvatarQuery);
|
if (!isInterstitialMode()) {
|
||||||
auto destinationBuffer = reinterpret_cast<unsigned char*>(avatarPacket->getPayload());
|
auto avatarPacket = NLPacket::create(PacketType::AvatarQuery);
|
||||||
unsigned char* bufferStart = destinationBuffer;
|
auto destinationBuffer = reinterpret_cast<unsigned char*>(avatarPacket->getPayload());
|
||||||
|
unsigned char* bufferStart = destinationBuffer;
|
||||||
|
|
||||||
uint8_t numFrustums = (uint8_t)_conicalViews.size();
|
uint8_t numFrustums = (uint8_t)_conicalViews.size();
|
||||||
memcpy(destinationBuffer, &numFrustums, sizeof(numFrustums));
|
memcpy(destinationBuffer, &numFrustums, sizeof(numFrustums));
|
||||||
destinationBuffer += sizeof(numFrustums);
|
destinationBuffer += sizeof(numFrustums);
|
||||||
|
|
||||||
for (const auto& view : _conicalViews) {
|
for (const auto& view : _conicalViews) {
|
||||||
destinationBuffer += view.serialize(destinationBuffer);
|
destinationBuffer += view.serialize(destinationBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
avatarPacket->setPayloadSize(destinationBuffer - bufferStart);
|
||||||
|
|
||||||
|
DependencyManager::get<NodeList>()->broadcastToNodes(std::move(avatarPacket), NodeSet() << NodeType::AvatarMixer);
|
||||||
}
|
}
|
||||||
|
|
||||||
avatarPacket->setPayloadSize(destinationBuffer - bufferStart);
|
|
||||||
|
|
||||||
DependencyManager::get<NodeList>()->broadcastToNodes(std::move(avatarPacket), NodeSet() << NodeType::AvatarMixer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -6350,6 +6392,7 @@ void Application::clearDomainOctreeDetails() {
|
||||||
qCDebug(interfaceapp) << "Clearing domain octree details...";
|
qCDebug(interfaceapp) << "Clearing domain octree details...";
|
||||||
|
|
||||||
resetPhysicsReadyInformation();
|
resetPhysicsReadyInformation();
|
||||||
|
setIsInterstitialMode(true);
|
||||||
|
|
||||||
_octreeServerSceneStats.withWriteLock([&] {
|
_octreeServerSceneStats.withWriteLock([&] {
|
||||||
_octreeServerSceneStats.clear();
|
_octreeServerSceneStats.clear();
|
||||||
|
@ -6370,10 +6413,6 @@ void Application::clearDomainOctreeDetails() {
|
||||||
getMyAvatar()->setAvatarEntityDataChanged(true);
|
getMyAvatar()->setAvatarEntityDataChanged(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::clearDomainAvatars() {
|
|
||||||
DependencyManager::get<AvatarManager>()->clearOtherAvatars();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::domainURLChanged(QUrl domainURL) {
|
void Application::domainURLChanged(QUrl domainURL) {
|
||||||
// disable physics until we have enough information about our new location to not cause craziness.
|
// disable physics until we have enough information about our new location to not cause craziness.
|
||||||
resetPhysicsReadyInformation();
|
resetPhysicsReadyInformation();
|
||||||
|
@ -6384,6 +6423,16 @@ void Application::domainURLChanged(QUrl domainURL) {
|
||||||
updateWindowTitle();
|
updateWindowTitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::goToErrorDomainURL(QUrl errorDomainURL) {
|
||||||
|
// disable physics until we have enough information about our new location to not cause craziness.
|
||||||
|
resetPhysicsReadyInformation();
|
||||||
|
setIsServerlessMode(errorDomainURL.scheme() != URL_SCHEME_HIFI);
|
||||||
|
if (isServerlessMode()) {
|
||||||
|
loadServerlessDomain(errorDomainURL, true);
|
||||||
|
}
|
||||||
|
updateWindowTitle();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Application::resettingDomain() {
|
void Application::resettingDomain() {
|
||||||
_notifiedPacketVersionMismatchThisDomain = false;
|
_notifiedPacketVersionMismatchThisDomain = false;
|
||||||
|
@ -6422,7 +6471,7 @@ void Application::nodeActivated(SharedNodePointer node) {
|
||||||
_octreeQuery.incrementConnectionID();
|
_octreeQuery.incrementConnectionID();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node->getType() == NodeType::AudioMixer) {
|
if (node->getType() == NodeType::AudioMixer && !isInterstitialMode()) {
|
||||||
DependencyManager::get<AudioClient>()->negotiateAudioFormat();
|
DependencyManager::get<AudioClient>()->negotiateAudioFormat();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6442,8 +6491,10 @@ void Application::nodeActivated(SharedNodePointer node) {
|
||||||
getMyAvatar()->markIdentityDataChanged();
|
getMyAvatar()->markIdentityDataChanged();
|
||||||
getMyAvatar()->resetLastSent();
|
getMyAvatar()->resetLastSent();
|
||||||
|
|
||||||
// transmit a "sendAll" packet to the AvatarMixer we just connected to.
|
if (!isInterstitialMode()) {
|
||||||
getMyAvatar()->sendAvatarDataPacket(true);
|
// transmit a "sendAll" packet to the AvatarMixer we just connected to.
|
||||||
|
getMyAvatar()->sendAvatarDataPacket(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6461,9 +6512,6 @@ void Application::nodeKilled(SharedNodePointer node) {
|
||||||
} else if (node->getType() == NodeType::EntityServer) {
|
} else if (node->getType() == NodeType::EntityServer) {
|
||||||
// we lost an entity server, clear all of the domain octree details
|
// we lost an entity server, clear all of the domain octree details
|
||||||
clearDomainOctreeDetails();
|
clearDomainOctreeDetails();
|
||||||
} else if (node->getType() == NodeType::AvatarMixer) {
|
|
||||||
// our avatar mixer has gone away - clear the hash of avatars
|
|
||||||
DependencyManager::get<AvatarManager>()->clearOtherAvatars();
|
|
||||||
} else if (node->getType() == NodeType::AssetServer) {
|
} else if (node->getType() == NodeType::AssetServer) {
|
||||||
// asset server going away - check if we have the asset browser showing
|
// asset server going away - check if we have the asset browser showing
|
||||||
|
|
||||||
|
@ -7797,7 +7845,7 @@ float Application::getRenderResolutionScale() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::notifyPacketVersionMismatch() {
|
void Application::notifyPacketVersionMismatch() {
|
||||||
if (!_notifiedPacketVersionMismatchThisDomain) {
|
if (!_notifiedPacketVersionMismatchThisDomain && !isInterstitialMode()) {
|
||||||
_notifiedPacketVersionMismatchThisDomain = true;
|
_notifiedPacketVersionMismatchThisDomain = true;
|
||||||
|
|
||||||
QString message = "The location you are visiting is running an incompatible server version.\n";
|
QString message = "The location you are visiting is running an incompatible server version.\n";
|
||||||
|
|
|
@ -224,6 +224,7 @@ public:
|
||||||
void setHmdTabletBecomesToolbarSetting(bool value);
|
void setHmdTabletBecomesToolbarSetting(bool value);
|
||||||
bool getPreferStylusOverLaser() { return _preferStylusOverLaserSetting.get(); }
|
bool getPreferStylusOverLaser() { return _preferStylusOverLaserSetting.get(); }
|
||||||
void setPreferStylusOverLaser(bool value);
|
void setPreferStylusOverLaser(bool value);
|
||||||
|
|
||||||
// FIXME: Remove setting completely or make available through JavaScript API?
|
// FIXME: Remove setting completely or make available through JavaScript API?
|
||||||
//bool getPreferAvatarFingerOverStylus() { return _preferAvatarFingerOverStylusSetting.get(); }
|
//bool getPreferAvatarFingerOverStylus() { return _preferAvatarFingerOverStylusSetting.get(); }
|
||||||
bool getPreferAvatarFingerOverStylus() { return false; }
|
bool getPreferAvatarFingerOverStylus() { return false; }
|
||||||
|
@ -304,6 +305,7 @@ public:
|
||||||
void saveNextPhysicsStats(QString filename);
|
void saveNextPhysicsStats(QString filename);
|
||||||
|
|
||||||
bool isServerlessMode() const;
|
bool isServerlessMode() const;
|
||||||
|
bool isInterstitialMode() const { return _interstitialMode; }
|
||||||
|
|
||||||
void replaceDomainContent(const QString& url);
|
void replaceDomainContent(const QString& url);
|
||||||
|
|
||||||
|
@ -331,6 +333,8 @@ signals:
|
||||||
|
|
||||||
void uploadRequest(QString path);
|
void uploadRequest(QString path);
|
||||||
|
|
||||||
|
void loginDialogPoppedUp();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
QVector<EntityItemID> pasteEntities(float x, float y, float z);
|
QVector<EntityItemID> pasteEntities(float x, float y, float z);
|
||||||
bool exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs, const glm::vec3* givenOffset = nullptr);
|
bool exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs, const glm::vec3* givenOffset = nullptr);
|
||||||
|
@ -338,6 +342,7 @@ public slots:
|
||||||
bool importEntities(const QString& url);
|
bool importEntities(const QString& url);
|
||||||
void updateThreadPoolCount() const;
|
void updateThreadPoolCount() const;
|
||||||
void updateSystemTabletMode();
|
void updateSystemTabletMode();
|
||||||
|
void goToErrorDomainURL(QUrl errorDomainURL);
|
||||||
|
|
||||||
Q_INVOKABLE void loadDialog();
|
Q_INVOKABLE void loadDialog();
|
||||||
Q_INVOKABLE void loadScriptURLDialog() const;
|
Q_INVOKABLE void loadScriptURLDialog() const;
|
||||||
|
@ -426,7 +431,8 @@ public slots:
|
||||||
void setPreferredCursor(const QString& cursor);
|
void setPreferredCursor(const QString& cursor);
|
||||||
|
|
||||||
void setIsServerlessMode(bool serverlessDomain);
|
void setIsServerlessMode(bool serverlessDomain);
|
||||||
void loadServerlessDomain(QUrl domainURL);
|
void loadServerlessDomain(QUrl domainURL, bool errorDomain = false);
|
||||||
|
void setIsInterstitialMode(bool interstialMode);
|
||||||
|
|
||||||
void updateVerboseLogging();
|
void updateVerboseLogging();
|
||||||
|
|
||||||
|
@ -437,7 +443,6 @@ private slots:
|
||||||
void onDesktopRootContextCreated(QQmlContext* qmlContext);
|
void onDesktopRootContextCreated(QQmlContext* qmlContext);
|
||||||
void showDesktop();
|
void showDesktop();
|
||||||
void clearDomainOctreeDetails();
|
void clearDomainOctreeDetails();
|
||||||
void clearDomainAvatars();
|
|
||||||
void onAboutToQuit();
|
void onAboutToQuit();
|
||||||
void onPresent(quint32 frameCount);
|
void onPresent(quint32 frameCount);
|
||||||
|
|
||||||
|
@ -626,6 +631,7 @@ private:
|
||||||
QHash<int, QKeyEvent> _keysPressed;
|
QHash<int, QKeyEvent> _keysPressed;
|
||||||
|
|
||||||
bool _enableProcessOctreeThread;
|
bool _enableProcessOctreeThread;
|
||||||
|
bool _interstitialMode { false };
|
||||||
|
|
||||||
OctreePacketProcessor _octreeProcessor;
|
OctreePacketProcessor _octreeProcessor;
|
||||||
EntityEditPacketSender _entityEditSender;
|
EntityEditPacketSender _entityEditSender;
|
||||||
|
|
|
@ -11,16 +11,18 @@
|
||||||
|
|
||||||
#include "ConnectionMonitor.h"
|
#include "ConnectionMonitor.h"
|
||||||
|
|
||||||
|
#include "Application.h"
|
||||||
#include "ui/DialogsManager.h"
|
#include "ui/DialogsManager.h"
|
||||||
|
|
||||||
#include <DependencyManager.h>
|
#include <DependencyManager.h>
|
||||||
#include <DomainHandler.h>
|
#include <DomainHandler.h>
|
||||||
|
#include <AddressManager.h>
|
||||||
#include <NodeList.h>
|
#include <NodeList.h>
|
||||||
|
|
||||||
// Because the connection monitor is created at startup, the time we wait on initial load
|
// Because the connection monitor is created at startup, the time we wait on initial load
|
||||||
// should be longer to allow the application to initialize.
|
// should be longer to allow the application to initialize.
|
||||||
static const int ON_INITIAL_LOAD_DISPLAY_AFTER_DISCONNECTED_FOR_X_MS = 10000;
|
static const int ON_INITIAL_LOAD_REDIRECT_AFTER_DISCONNECTED_FOR_X_MS = 10000;
|
||||||
static const int DISPLAY_AFTER_DISCONNECTED_FOR_X_MS = 5000;
|
static const int REDIRECT_AFTER_DISCONNECTED_FOR_X_MS = 5000;
|
||||||
|
|
||||||
void ConnectionMonitor::init() {
|
void ConnectionMonitor::init() {
|
||||||
// Connect to domain disconnected message
|
// Connect to domain disconnected message
|
||||||
|
@ -30,23 +32,25 @@ void ConnectionMonitor::init() {
|
||||||
connect(&domainHandler, &DomainHandler::disconnectedFromDomain, this, &ConnectionMonitor::startTimer);
|
connect(&domainHandler, &DomainHandler::disconnectedFromDomain, this, &ConnectionMonitor::startTimer);
|
||||||
connect(&domainHandler, &DomainHandler::connectedToDomain, this, &ConnectionMonitor::stopTimer);
|
connect(&domainHandler, &DomainHandler::connectedToDomain, this, &ConnectionMonitor::stopTimer);
|
||||||
connect(&domainHandler, &DomainHandler::domainConnectionRefused, this, &ConnectionMonitor::stopTimer);
|
connect(&domainHandler, &DomainHandler::domainConnectionRefused, this, &ConnectionMonitor::stopTimer);
|
||||||
|
connect(&domainHandler, &DomainHandler::redirectToErrorDomainURL, this, &ConnectionMonitor::stopTimer);
|
||||||
|
connect(this, &ConnectionMonitor::setRedirectErrorState, &domainHandler, &DomainHandler::setRedirectErrorState);
|
||||||
|
|
||||||
_timer.setSingleShot(true);
|
_timer.setSingleShot(true);
|
||||||
if (!domainHandler.isConnected()) {
|
if (!domainHandler.isConnected()) {
|
||||||
_timer.start(ON_INITIAL_LOAD_DISPLAY_AFTER_DISCONNECTED_FOR_X_MS);
|
_timer.start(ON_INITIAL_LOAD_REDIRECT_AFTER_DISCONNECTED_FOR_X_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
connect(&_timer, &QTimer::timeout, this, []() {
|
connect(&_timer, &QTimer::timeout, this, [this]() {
|
||||||
qDebug() << "ConnectionMonitor: Showing connection failure window";
|
qDebug() << "ConnectionMonitor: Redirecting to 404 error domain";
|
||||||
DependencyManager::get<DialogsManager>()->setDomainConnectionFailureVisibility(true);
|
// set in a timeout error
|
||||||
|
emit setRedirectErrorState(REDIRECT_HIFI_ADDRESS, 5);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionMonitor::startTimer() {
|
void ConnectionMonitor::startTimer() {
|
||||||
_timer.start(DISPLAY_AFTER_DISCONNECTED_FOR_X_MS);
|
_timer.start(REDIRECT_AFTER_DISCONNECTED_FOR_X_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionMonitor::stopTimer() {
|
void ConnectionMonitor::stopTimer() {
|
||||||
_timer.stop();
|
_timer.stop();
|
||||||
DependencyManager::get<DialogsManager>()->setDomainConnectionFailureVisibility(false);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
|
class QUrl;
|
||||||
class QString;
|
class QString;
|
||||||
|
|
||||||
class ConnectionMonitor : public QObject {
|
class ConnectionMonitor : public QObject {
|
||||||
|
@ -22,6 +23,9 @@ class ConnectionMonitor : public QObject {
|
||||||
public:
|
public:
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void setRedirectErrorState(QUrl errorURL, int reasonCode);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void startTimer();
|
void startTimer();
|
||||||
void stopTimer();
|
void stopTimer();
|
||||||
|
|
|
@ -137,7 +137,7 @@ void AvatarManager::updateMyAvatar(float deltaTime) {
|
||||||
quint64 now = usecTimestampNow();
|
quint64 now = usecTimestampNow();
|
||||||
quint64 dt = now - _lastSendAvatarDataTime;
|
quint64 dt = now - _lastSendAvatarDataTime;
|
||||||
|
|
||||||
if (dt > MIN_TIME_BETWEEN_MY_AVATAR_DATA_SENDS) {
|
if (dt > MIN_TIME_BETWEEN_MY_AVATAR_DATA_SENDS && !_myAvatarDataPacketsPaused) {
|
||||||
// send head/hand data to the avatar mixer and voxel server
|
// send head/hand data to the avatar mixer and voxel server
|
||||||
PerformanceTimer perfTimer("send");
|
PerformanceTimer perfTimer("send");
|
||||||
_myAvatar->sendAvatarDataPacket();
|
_myAvatar->sendAvatarDataPacket();
|
||||||
|
@ -155,6 +155,16 @@ float AvatarManager::getAvatarDataRate(const QUuid& sessionID, const QString& ra
|
||||||
return avatar ? avatar->getDataRate(rateName) : 0.0f;
|
return avatar ? avatar->getDataRate(rateName) : 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AvatarManager::setMyAvatarDataPacketsPaused(bool pause) {
|
||||||
|
if (_myAvatarDataPacketsPaused != pause) {
|
||||||
|
_myAvatarDataPacketsPaused = pause;
|
||||||
|
|
||||||
|
if (!_myAvatarDataPacketsPaused) {
|
||||||
|
_myAvatar->sendAvatarDataPacket(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
float AvatarManager::getAvatarUpdateRate(const QUuid& sessionID, const QString& rateName) const {
|
float AvatarManager::getAvatarUpdateRate(const QUuid& sessionID, const QString& rateName) const {
|
||||||
auto avatar = getAvatarBySessionID(sessionID);
|
auto avatar = getAvatarBySessionID(sessionID);
|
||||||
return avatar ? avatar->getUpdateRate(rateName) : 0.0f;
|
return avatar ? avatar->getUpdateRate(rateName) : 0.0f;
|
||||||
|
@ -802,13 +812,13 @@ void AvatarManager::setAvatarSortCoefficient(const QString& name, const QScriptV
|
||||||
QString currentSessionUUID = avatar->getSessionUUID().toString();
|
QString currentSessionUUID = avatar->getSessionUUID().toString();
|
||||||
if (specificAvatarIdentifiers.isEmpty() || specificAvatarIdentifiers.contains(currentSessionUUID)) {
|
if (specificAvatarIdentifiers.isEmpty() || specificAvatarIdentifiers.contains(currentSessionUUID)) {
|
||||||
QJsonObject thisAvatarPalData;
|
QJsonObject thisAvatarPalData;
|
||||||
|
|
||||||
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||||
|
|
||||||
if (currentSessionUUID == myAvatar->getSessionUUID().toString()) {
|
if (currentSessionUUID == myAvatar->getSessionUUID().toString()) {
|
||||||
currentSessionUUID = "";
|
currentSessionUUID = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
thisAvatarPalData.insert("sessionUUID", currentSessionUUID);
|
thisAvatarPalData.insert("sessionUUID", currentSessionUUID);
|
||||||
thisAvatarPalData.insert("sessionDisplayName", avatar->getSessionDisplayName());
|
thisAvatarPalData.insert("sessionDisplayName", avatar->getSessionDisplayName());
|
||||||
thisAvatarPalData.insert("audioLoudness", avatar->getAudioLoudness());
|
thisAvatarPalData.insert("audioLoudness", avatar->getAudioLoudness());
|
||||||
|
|
|
@ -91,9 +91,11 @@ public:
|
||||||
void updateOtherAvatars(float deltaTime);
|
void updateOtherAvatars(float deltaTime);
|
||||||
void sendIdentityRequest(const QUuid& avatarID) const;
|
void sendIdentityRequest(const QUuid& avatarID) const;
|
||||||
|
|
||||||
|
void setMyAvatarDataPacketsPaused(bool puase);
|
||||||
|
|
||||||
void postUpdate(float deltaTime, const render::ScenePointer& scene);
|
void postUpdate(float deltaTime, const render::ScenePointer& scene);
|
||||||
|
|
||||||
void clearOtherAvatars();
|
void clearOtherAvatars() override;
|
||||||
void deleteAllAvatars();
|
void deleteAllAvatars();
|
||||||
|
|
||||||
void getObjectsToRemoveFromPhysics(VectorOfMotionStates& motionStates);
|
void getObjectsToRemoveFromPhysics(VectorOfMotionStates& motionStates);
|
||||||
|
@ -219,6 +221,7 @@ private:
|
||||||
int _numAvatarsNotUpdated { 0 };
|
int _numAvatarsNotUpdated { 0 };
|
||||||
float _avatarSimulationTime { 0.0f };
|
float _avatarSimulationTime { 0.0f };
|
||||||
bool _shouldRender { true };
|
bool _shouldRender { true };
|
||||||
|
bool _myAvatarDataPacketsPaused { false };
|
||||||
mutable int _identityRequestsSent { 0 };
|
mutable int _identityRequestsSent { 0 };
|
||||||
|
|
||||||
mutable std::mutex _spaceLock;
|
mutable std::mutex _spaceLock;
|
||||||
|
|
|
@ -11,6 +11,25 @@
|
||||||
|
|
||||||
#include "AvatarMotionState.h"
|
#include "AvatarMotionState.h"
|
||||||
|
|
||||||
|
static xColor getLoadingOrbColor(Avatar::LoadingStatus loadingStatus) {
|
||||||
|
|
||||||
|
const xColor NO_MODEL_COLOR(0xe3, 0xe3, 0xe3);
|
||||||
|
const xColor LOAD_MODEL_COLOR(0xef, 0x93, 0xd1);
|
||||||
|
const xColor LOAD_SUCCESS_COLOR(0x1f, 0xc6, 0xa6);
|
||||||
|
const xColor LOAD_FAILURE_COLOR(0xc6, 0x21, 0x47);
|
||||||
|
switch (loadingStatus) {
|
||||||
|
case Avatar::LoadingStatus::NoModel:
|
||||||
|
return NO_MODEL_COLOR;
|
||||||
|
case Avatar::LoadingStatus::LoadModel:
|
||||||
|
return LOAD_MODEL_COLOR;
|
||||||
|
case Avatar::LoadingStatus::LoadSuccess:
|
||||||
|
return LOAD_SUCCESS_COLOR;
|
||||||
|
case Avatar::LoadingStatus::LoadFailure:
|
||||||
|
default:
|
||||||
|
return LOAD_FAILURE_COLOR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
OtherAvatar::OtherAvatar(QThread* thread) : Avatar(thread) {
|
OtherAvatar::OtherAvatar(QThread* thread) : Avatar(thread) {
|
||||||
// give the pointer to our head to inherited _headData variable from AvatarData
|
// give the pointer to our head to inherited _headData variable from AvatarData
|
||||||
_headData = new Head(this);
|
_headData = new Head(this);
|
||||||
|
@ -48,7 +67,7 @@ void OtherAvatar::createOrb() {
|
||||||
if (_otherAvatarOrbMeshPlaceholderID.isNull()) {
|
if (_otherAvatarOrbMeshPlaceholderID.isNull()) {
|
||||||
_otherAvatarOrbMeshPlaceholder = std::make_shared<Sphere3DOverlay>();
|
_otherAvatarOrbMeshPlaceholder = std::make_shared<Sphere3DOverlay>();
|
||||||
_otherAvatarOrbMeshPlaceholder->setAlpha(1.0f);
|
_otherAvatarOrbMeshPlaceholder->setAlpha(1.0f);
|
||||||
_otherAvatarOrbMeshPlaceholder->setColor({ 0xFF, 0x00, 0xFF });
|
_otherAvatarOrbMeshPlaceholder->setColor(getLoadingOrbColor(_loadingStatus));
|
||||||
_otherAvatarOrbMeshPlaceholder->setIsSolid(false);
|
_otherAvatarOrbMeshPlaceholder->setIsSolid(false);
|
||||||
_otherAvatarOrbMeshPlaceholder->setPulseMin(0.5);
|
_otherAvatarOrbMeshPlaceholder->setPulseMin(0.5);
|
||||||
_otherAvatarOrbMeshPlaceholder->setPulseMax(1.0);
|
_otherAvatarOrbMeshPlaceholder->setPulseMax(1.0);
|
||||||
|
@ -64,6 +83,13 @@ void OtherAvatar::createOrb() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OtherAvatar::indicateLoadingStatus(LoadingStatus loadingStatus) {
|
||||||
|
Avatar::indicateLoadingStatus(loadingStatus);
|
||||||
|
if (_otherAvatarOrbMeshPlaceholder) {
|
||||||
|
_otherAvatarOrbMeshPlaceholder->setColor(getLoadingOrbColor(_loadingStatus));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void OtherAvatar::setSpaceIndex(int32_t index) {
|
void OtherAvatar::setSpaceIndex(int32_t index) {
|
||||||
assert(_spaceIndex == -1);
|
assert(_spaceIndex == -1);
|
||||||
_spaceIndex = index;
|
_spaceIndex = index;
|
||||||
|
|
|
@ -28,6 +28,7 @@ public:
|
||||||
|
|
||||||
virtual void instantiableAvatar() override { };
|
virtual void instantiableAvatar() override { };
|
||||||
virtual void createOrb() override;
|
virtual void createOrb() override;
|
||||||
|
virtual void indicateLoadingStatus(LoadingStatus loadingStatus) override;
|
||||||
void updateOrbPosition();
|
void updateOrbPosition();
|
||||||
void removeOrb();
|
void removeOrb();
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "Menu.h"
|
#include "Menu.h"
|
||||||
#include "SceneScriptingInterface.h"
|
#include "SceneScriptingInterface.h"
|
||||||
#include "SafeLanding.h"
|
|
||||||
|
|
||||||
OctreePacketProcessor::OctreePacketProcessor():
|
OctreePacketProcessor::OctreePacketProcessor():
|
||||||
_safeLanding(new SafeLanding())
|
_safeLanding(new SafeLanding())
|
||||||
|
@ -133,7 +132,3 @@ void OctreePacketProcessor::processPacket(QSharedPointer<ReceivedMessage> messag
|
||||||
void OctreePacketProcessor::startEntitySequence() {
|
void OctreePacketProcessor::startEntitySequence() {
|
||||||
_safeLanding->startEntitySequence(qApp->getEntities());
|
_safeLanding->startEntitySequence(qApp->getEntities());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OctreePacketProcessor::isLoadSequenceComplete() const {
|
|
||||||
return _safeLanding->isLoadSequenceComplete();
|
|
||||||
}
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
#include <ReceivedPacketProcessor.h>
|
#include <ReceivedPacketProcessor.h>
|
||||||
#include <ReceivedMessage.h>
|
#include <ReceivedMessage.h>
|
||||||
|
|
||||||
class SafeLanding;
|
#include "SafeLanding.h"
|
||||||
|
|
||||||
/// Handles processing of incoming voxel packets for the interface application. As with other ReceivedPacketProcessor classes
|
/// Handles processing of incoming voxel packets for the interface application. As with other ReceivedPacketProcessor classes
|
||||||
/// the user is responsible for reading inbound packets and adding them to the processing queue by calling queueReceivedPacket()
|
/// the user is responsible for reading inbound packets and adding them to the processing queue by calling queueReceivedPacket()
|
||||||
|
@ -26,7 +26,8 @@ public:
|
||||||
~OctreePacketProcessor();
|
~OctreePacketProcessor();
|
||||||
|
|
||||||
void startEntitySequence();
|
void startEntitySequence();
|
||||||
bool isLoadSequenceComplete() const;
|
bool isLoadSequenceComplete() const { return _safeLanding->isLoadSequenceComplete(); }
|
||||||
|
float domainLoadingProgress() const { return _safeLanding->loadingProgressPercentage(); }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void packetVersionMismatch();
|
void packetVersionMismatch();
|
||||||
|
@ -40,4 +41,4 @@ private slots:
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<SafeLanding> _safeLanding;
|
std::unique_ptr<SafeLanding> _safeLanding;
|
||||||
};
|
};
|
||||||
#endif // hifi_OctreePacketProcessor_h
|
#endif // hifi_OctreePacketProcessor_h
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "EntityTreeRenderer.h"
|
#include "EntityTreeRenderer.h"
|
||||||
#include "ModelEntityItem.h"
|
#include "ModelEntityItem.h"
|
||||||
#include "InterfaceLogging.h"
|
#include "InterfaceLogging.h"
|
||||||
|
#include "Application.h"
|
||||||
|
|
||||||
const int SafeLanding::SEQUENCE_MODULO = std::numeric_limits<OCTREE_PACKET_SEQUENCE>::max() + 1;
|
const int SafeLanding::SEQUENCE_MODULO = std::numeric_limits<OCTREE_PACKET_SEQUENCE>::max() + 1;
|
||||||
|
|
||||||
|
@ -53,6 +54,7 @@ void SafeLanding::startEntitySequence(QSharedPointer<EntityTreeRenderer> entityT
|
||||||
void SafeLanding::stopEntitySequence() {
|
void SafeLanding::stopEntitySequence() {
|
||||||
Locker lock(_lock);
|
Locker lock(_lock);
|
||||||
_trackingEntities = false;
|
_trackingEntities = false;
|
||||||
|
_maxTrackedEntityCount = 0;
|
||||||
_initialStart = INVALID_SEQUENCE;
|
_initialStart = INVALID_SEQUENCE;
|
||||||
_initialEnd = INVALID_SEQUENCE;
|
_initialEnd = INVALID_SEQUENCE;
|
||||||
_trackedEntities.clear();
|
_trackedEntities.clear();
|
||||||
|
@ -64,20 +66,13 @@ void SafeLanding::addTrackedEntity(const EntityItemID& entityID) {
|
||||||
Locker lock(_lock);
|
Locker lock(_lock);
|
||||||
EntityItemPointer entity = _entityTree->findEntityByID(entityID);
|
EntityItemPointer entity = _entityTree->findEntityByID(entityID);
|
||||||
|
|
||||||
if (entity && !entity->getCollisionless()) {
|
_trackedEntities.emplace(entityID, entity);
|
||||||
const auto& entityType = entity->getType();
|
int trackedEntityCount = (int)_trackedEntities.size();
|
||||||
if (entityType == EntityTypes::Model) {
|
|
||||||
ModelEntityItem * modelEntity = std::dynamic_pointer_cast<ModelEntityItem>(entity).get();
|
if (trackedEntityCount > _maxTrackedEntityCount) {
|
||||||
static const std::set<ShapeType> downloadedCollisionTypes
|
_maxTrackedEntityCount = trackedEntityCount;
|
||||||
{ SHAPE_TYPE_COMPOUND, SHAPE_TYPE_SIMPLE_COMPOUND, SHAPE_TYPE_STATIC_MESH, SHAPE_TYPE_SIMPLE_HULL };
|
|
||||||
bool hasAABox;
|
|
||||||
entity->getAABox(hasAABox);
|
|
||||||
if (hasAABox && downloadedCollisionTypes.count(modelEntity->getShapeType()) != 0) {
|
|
||||||
// Only track entities with downloaded collision bodies.
|
|
||||||
_trackedEntities.emplace(entityID, entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
qCDebug(interfaceapp) << "Safe Landing: Tracking entity " << entity->getItemName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +97,7 @@ void SafeLanding::noteReceivedsequenceNumber(int sequenceNumber) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SafeLanding::isLoadSequenceComplete() {
|
bool SafeLanding::isLoadSequenceComplete() {
|
||||||
if (isEntityPhysicsComplete() && isSequenceNumbersComplete()) {
|
if (isEntityLoadingComplete() && isSequenceNumbersComplete()) {
|
||||||
Locker lock(_lock);
|
Locker lock(_lock);
|
||||||
_trackedEntities.clear();
|
_trackedEntities.clear();
|
||||||
_initialStart = INVALID_SEQUENCE;
|
_initialStart = INVALID_SEQUENCE;
|
||||||
|
@ -114,6 +109,15 @@ bool SafeLanding::isLoadSequenceComplete() {
|
||||||
return !_trackingEntities;
|
return !_trackingEntities;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float SafeLanding::loadingProgressPercentage() {
|
||||||
|
Locker lock(_lock);
|
||||||
|
if (_maxTrackedEntityCount > 0) {
|
||||||
|
return ((_maxTrackedEntityCount - _trackedEntities.size()) / (float)_maxTrackedEntityCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
bool SafeLanding::isSequenceNumbersComplete() {
|
bool SafeLanding::isSequenceNumbersComplete() {
|
||||||
if (_initialStart != INVALID_SEQUENCE) {
|
if (_initialStart != INVALID_SEQUENCE) {
|
||||||
Locker lock(_lock);
|
Locker lock(_lock);
|
||||||
|
@ -132,17 +136,42 @@ bool SafeLanding::isSequenceNumbersComplete() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SafeLanding::isEntityPhysicsComplete() {
|
bool isEntityPhysicsReady(const EntityItemPointer& entity) {
|
||||||
Locker lock(_lock);
|
if (entity && !entity->getCollisionless()) {
|
||||||
for (auto entityMapIter = _trackedEntities.begin(); entityMapIter != _trackedEntities.end(); ++entityMapIter) {
|
const auto& entityType = entity->getType();
|
||||||
auto entity = entityMapIter->second;
|
if (entityType == EntityTypes::Model) {
|
||||||
if (!entity->shouldBePhysical() || entity->isReadyToComputeShape()) {
|
ModelEntityItem * modelEntity = std::dynamic_pointer_cast<ModelEntityItem>(entity).get();
|
||||||
entityMapIter = _trackedEntities.erase(entityMapIter);
|
static const std::set<ShapeType> downloadedCollisionTypes
|
||||||
if (entityMapIter == _trackedEntities.end()) {
|
{ SHAPE_TYPE_COMPOUND, SHAPE_TYPE_SIMPLE_COMPOUND, SHAPE_TYPE_STATIC_MESH, SHAPE_TYPE_SIMPLE_HULL };
|
||||||
break;
|
bool hasAABox;
|
||||||
|
entity->getAABox(hasAABox);
|
||||||
|
if (hasAABox && downloadedCollisionTypes.count(modelEntity->getShapeType()) != 0) {
|
||||||
|
return entity->isReadyToComputeShape();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SafeLanding::isEntityLoadingComplete() {
|
||||||
|
Locker lock(_lock);
|
||||||
|
auto entityTree = qApp->getEntities();
|
||||||
|
auto entityMapIter = _trackedEntities.begin();
|
||||||
|
|
||||||
|
while (entityMapIter != _trackedEntities.end()) {
|
||||||
|
auto entity = entityMapIter->second;
|
||||||
|
bool isVisuallyReady = (entity->isVisuallyReady() || !entityTree->renderableForEntityId(entityMapIter->first));
|
||||||
|
if (isEntityPhysicsReady(entity) && isVisuallyReady) {
|
||||||
|
entityMapIter = _trackedEntities.erase(entityMapIter);
|
||||||
|
} else {
|
||||||
|
if (!isVisuallyReady) {
|
||||||
|
entity->requestRenderUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
entityMapIter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
return _trackedEntities.empty();
|
return _trackedEntities.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <QtCore/QSharedPointer>
|
#include <QtCore/QSharedPointer>
|
||||||
|
|
||||||
#include "EntityItem.h"
|
#include "EntityItem.h"
|
||||||
|
#include "EntityDynamicInterface.h"
|
||||||
|
|
||||||
class EntityTreeRenderer;
|
class EntityTreeRenderer;
|
||||||
class EntityItemID;
|
class EntityItemID;
|
||||||
|
@ -29,6 +30,7 @@ public:
|
||||||
void setCompletionSequenceNumbers(int first, int last); // 'last' exclusive.
|
void setCompletionSequenceNumbers(int first, int last); // 'last' exclusive.
|
||||||
void noteReceivedsequenceNumber(int sequenceNumber);
|
void noteReceivedsequenceNumber(int sequenceNumber);
|
||||||
bool isLoadSequenceComplete();
|
bool isLoadSequenceComplete();
|
||||||
|
float loadingProgressPercentage();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void addTrackedEntity(const EntityItemID& entityID);
|
void addTrackedEntity(const EntityItemID& entityID);
|
||||||
|
@ -37,7 +39,7 @@ private slots:
|
||||||
private:
|
private:
|
||||||
bool isSequenceNumbersComplete();
|
bool isSequenceNumbersComplete();
|
||||||
void debugDumpSequenceIDs() const;
|
void debugDumpSequenceIDs() const;
|
||||||
bool isEntityPhysicsComplete();
|
bool isEntityLoadingComplete();
|
||||||
|
|
||||||
std::mutex _lock;
|
std::mutex _lock;
|
||||||
using Locker = std::lock_guard<std::mutex>;
|
using Locker = std::lock_guard<std::mutex>;
|
||||||
|
@ -49,6 +51,7 @@ private:
|
||||||
static constexpr int INVALID_SEQUENCE = -1;
|
static constexpr int INVALID_SEQUENCE = -1;
|
||||||
int _initialStart { INVALID_SEQUENCE };
|
int _initialStart { INVALID_SEQUENCE };
|
||||||
int _initialEnd { INVALID_SEQUENCE };
|
int _initialEnd { INVALID_SEQUENCE };
|
||||||
|
int _maxTrackedEntityCount { 0 };
|
||||||
|
|
||||||
struct SequenceLessThan {
|
struct SequenceLessThan {
|
||||||
bool operator()(const int& a, const int& b) const;
|
bool operator()(const int& a, const int& b) const;
|
||||||
|
|
|
@ -409,6 +409,10 @@ glm::vec2 WindowScriptingInterface::getDeviceSize() const {
|
||||||
return qApp->getDeviceSize();
|
return qApp->getDeviceSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int WindowScriptingInterface::getLastDomainConnectionError() const {
|
||||||
|
return DependencyManager::get<NodeList>()->getDomainHandler().getLastDomainConnectionError();
|
||||||
|
}
|
||||||
|
|
||||||
int WindowScriptingInterface::getX() {
|
int WindowScriptingInterface::getX() {
|
||||||
return qApp->getWindow()->geometry().x();
|
return qApp->getWindow()->geometry().x();
|
||||||
}
|
}
|
||||||
|
@ -584,3 +588,8 @@ void WindowScriptingInterface::onMessageBoxSelected(int button) {
|
||||||
_messageBoxes.remove(id);
|
_messageBoxes.remove(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float WindowScriptingInterface::domainLoadingProgress() {
|
||||||
|
return qApp->getOctreePacketProcessor().domainLoadingProgress();
|
||||||
|
}
|
||||||
|
|
|
@ -491,6 +491,13 @@ public slots:
|
||||||
*/
|
*/
|
||||||
glm::vec2 getDeviceSize() const;
|
glm::vec2 getDeviceSize() const;
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Gets the last domain connection error when a connection is refused.
|
||||||
|
* @function Window.getLastDomainConnectionError
|
||||||
|
* @returns {Window.ConnectionRefusedReason} Integer number that enumerates the last domain connection refused.
|
||||||
|
*/
|
||||||
|
int getLastDomainConnectionError() const;
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Open a non-modal message box that can have a variety of button combinations. See also,
|
* Open a non-modal message box that can have a variety of button combinations. See also,
|
||||||
* {@link Window.updateMessageBox|updateMessageBox} and {@link Window.closeMessageBox|closeMessageBox}.
|
* {@link Window.updateMessageBox|updateMessageBox} and {@link Window.closeMessageBox|closeMessageBox}.
|
||||||
|
@ -561,6 +568,8 @@ public slots:
|
||||||
*/
|
*/
|
||||||
void closeMessageBox(int id);
|
void closeMessageBox(int id);
|
||||||
|
|
||||||
|
float domainLoadingProgress();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onWindowGeometryChanged(const QRect& geometry);
|
void onWindowGeometryChanged(const QRect& geometry);
|
||||||
void onMessageBoxSelected(int button);
|
void onMessageBoxSelected(int button);
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <plugins/PluginManager.h>
|
#include <plugins/PluginManager.h>
|
||||||
#include <plugins/SteamClientPlugin.h>
|
#include <plugins/SteamClientPlugin.h>
|
||||||
#include <ui/TabletScriptingInterface.h>
|
#include <ui/TabletScriptingInterface.h>
|
||||||
|
#include <UserActivityLogger.h>
|
||||||
|
|
||||||
#include "AccountManager.h"
|
#include "AccountManager.h"
|
||||||
#include "DependencyManager.h"
|
#include "DependencyManager.h"
|
||||||
|
@ -37,11 +38,19 @@ LoginDialog::LoginDialog(QQuickItem *parent) : OffscreenQmlDialog(parent) {
|
||||||
connect(accountManager.data(), &AccountManager::loginFailed,
|
connect(accountManager.data(), &AccountManager::loginFailed,
|
||||||
this, &LoginDialog::handleLoginFailed);
|
this, &LoginDialog::handleLoginFailed);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoginDialog::showWithSelection()
|
LoginDialog::~LoginDialog() {
|
||||||
{
|
Setting::Handle<bool> loginDialogPoppedUp{ "loginDialogPoppedUp", false };
|
||||||
|
if (loginDialogPoppedUp.get()) {
|
||||||
|
QJsonObject data;
|
||||||
|
data["action"] = "user opted out";
|
||||||
|
UserActivityLogger::getInstance().logAction("encourageLoginDialog", data);
|
||||||
|
}
|
||||||
|
loginDialogPoppedUp.set(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoginDialog::showWithSelection() {
|
||||||
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
||||||
auto tablet = dynamic_cast<TabletProxy*>(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"));
|
auto tablet = dynamic_cast<TabletProxy*>(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"));
|
||||||
auto hmd = DependencyManager::get<HMDScriptingInterface>();
|
auto hmd = DependencyManager::get<HMDScriptingInterface>();
|
||||||
|
@ -73,9 +82,7 @@ void LoginDialog::toggleAction() {
|
||||||
} else {
|
} else {
|
||||||
// change the menu item to login
|
// change the menu item to login
|
||||||
loginAction->setText("Login / Sign Up");
|
loginAction->setText("Login / Sign Up");
|
||||||
connection = connect(loginAction, &QAction::triggered, [] {
|
connection = connect(loginAction, &QAction::triggered, [] { LoginDialog::showWithSelection(); });
|
||||||
LoginDialog::showWithSelection();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,7 +165,6 @@ void LoginDialog::createAccountFromStream(QString username) {
|
||||||
QJsonDocument(payload).toJson());
|
QJsonDocument(payload).toJson());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoginDialog::openUrl(const QString& url) const {
|
void LoginDialog::openUrl(const QString& url) const {
|
||||||
|
@ -200,25 +206,24 @@ void LoginDialog::createFailed(QNetworkReply* reply) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoginDialog::signup(const QString& email, const QString& username, const QString& password) {
|
void LoginDialog::signup(const QString& email, const QString& username, const QString& password) {
|
||||||
|
|
||||||
JSONCallbackParameters callbackParams;
|
JSONCallbackParameters callbackParams;
|
||||||
callbackParams.callbackReceiver = this;
|
callbackParams.callbackReceiver = this;
|
||||||
callbackParams.jsonCallbackMethod = "signupCompleted";
|
callbackParams.jsonCallbackMethod = "signupCompleted";
|
||||||
callbackParams.errorCallbackMethod = "signupFailed";
|
callbackParams.errorCallbackMethod = "signupFailed";
|
||||||
|
|
||||||
QJsonObject payload;
|
QJsonObject payload;
|
||||||
|
|
||||||
QJsonObject userObject;
|
QJsonObject userObject;
|
||||||
userObject.insert("email", email);
|
userObject.insert("email", email);
|
||||||
userObject.insert("username", username);
|
userObject.insert("username", username);
|
||||||
userObject.insert("password", password);
|
userObject.insert("password", password);
|
||||||
|
|
||||||
payload.insert("user", userObject);
|
payload.insert("user", userObject);
|
||||||
|
|
||||||
static const QString API_SIGNUP_PATH = "api/v1/users";
|
static const QString API_SIGNUP_PATH = "api/v1/users";
|
||||||
|
|
||||||
qDebug() << "Sending a request to create an account for" << username;
|
qDebug() << "Sending a request to create an account for" << username;
|
||||||
|
|
||||||
auto accountManager = DependencyManager::get<AccountManager>();
|
auto accountManager = DependencyManager::get<AccountManager>();
|
||||||
accountManager->sendRequest(API_SIGNUP_PATH, AccountManagerAuth::None,
|
accountManager->sendRequest(API_SIGNUP_PATH, AccountManagerAuth::None,
|
||||||
QNetworkAccessManager::PostOperation, callbackParams,
|
QNetworkAccessManager::PostOperation, callbackParams,
|
||||||
|
@ -240,41 +245,37 @@ QString errorStringFromAPIObject(const QJsonValue& apiObject) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoginDialog::signupFailed(QNetworkReply* reply) {
|
void LoginDialog::signupFailed(QNetworkReply* reply) {
|
||||||
|
|
||||||
// parse the returned JSON to see what the problem was
|
// parse the returned JSON to see what the problem was
|
||||||
auto jsonResponse = QJsonDocument::fromJson(reply->readAll());
|
auto jsonResponse = QJsonDocument::fromJson(reply->readAll());
|
||||||
|
|
||||||
static const QString RESPONSE_DATA_KEY = "data";
|
static const QString RESPONSE_DATA_KEY = "data";
|
||||||
|
|
||||||
auto dataJsonValue = jsonResponse.object()[RESPONSE_DATA_KEY];
|
auto dataJsonValue = jsonResponse.object()[RESPONSE_DATA_KEY];
|
||||||
|
|
||||||
if (dataJsonValue.isObject()) {
|
if (dataJsonValue.isObject()) {
|
||||||
auto dataObject = dataJsonValue.toObject();
|
auto dataObject = dataJsonValue.toObject();
|
||||||
|
|
||||||
static const QString EMAIL_DATA_KEY = "email";
|
static const QString EMAIL_DATA_KEY = "email";
|
||||||
static const QString USERNAME_DATA_KEY = "username";
|
static const QString USERNAME_DATA_KEY = "username";
|
||||||
static const QString PASSWORD_DATA_KEY = "password";
|
static const QString PASSWORD_DATA_KEY = "password";
|
||||||
|
|
||||||
QStringList errorStringList;
|
QStringList errorStringList;
|
||||||
|
|
||||||
if (dataObject.contains(EMAIL_DATA_KEY)) {
|
if (dataObject.contains(EMAIL_DATA_KEY)) {
|
||||||
errorStringList.append(QString("Email %1.").arg(errorStringFromAPIObject(dataObject[EMAIL_DATA_KEY])));
|
errorStringList.append(QString("Email %1.").arg(errorStringFromAPIObject(dataObject[EMAIL_DATA_KEY])));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dataObject.contains(USERNAME_DATA_KEY)) {
|
if (dataObject.contains(USERNAME_DATA_KEY)) {
|
||||||
errorStringList.append(QString("Username %1.").arg(errorStringFromAPIObject(dataObject[USERNAME_DATA_KEY])));
|
errorStringList.append(QString("Username %1.").arg(errorStringFromAPIObject(dataObject[USERNAME_DATA_KEY])));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dataObject.contains(PASSWORD_DATA_KEY)) {
|
if (dataObject.contains(PASSWORD_DATA_KEY)) {
|
||||||
errorStringList.append(QString("Password %1.").arg(errorStringFromAPIObject(dataObject[PASSWORD_DATA_KEY])));
|
errorStringList.append(QString("Password %1.").arg(errorStringFromAPIObject(dataObject[PASSWORD_DATA_KEY])));
|
||||||
}
|
}
|
||||||
|
|
||||||
emit handleSignupFailed(errorStringList.join('\n'));
|
emit handleSignupFailed(errorStringList.join('\n'));
|
||||||
} else {
|
} else {
|
||||||
static const QString DEFAULT_SIGN_UP_FAILURE_MESSAGE = "There was an unknown error while creating your account. Please try again later.";
|
static const QString DEFAULT_SIGN_UP_FAILURE_MESSAGE = "There was an unknown error while creating your account. Please try again later.";
|
||||||
emit handleSignupFailed(DEFAULT_SIGN_UP_FAILURE_MESSAGE);
|
emit handleSignupFailed(DEFAULT_SIGN_UP_FAILURE_MESSAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,10 @@ public:
|
||||||
|
|
||||||
LoginDialog(QQuickItem* parent = nullptr);
|
LoginDialog(QQuickItem* parent = nullptr);
|
||||||
|
|
||||||
|
~LoginDialog();
|
||||||
|
|
||||||
static void showWithSelection();
|
static void showWithSelection();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void handleLoginCompleted();
|
void handleLoginCompleted();
|
||||||
void handleLoginFailed();
|
void handleLoginFailed();
|
||||||
|
@ -62,7 +65,6 @@ protected slots:
|
||||||
Q_INVOKABLE void signup(const QString& email, const QString& username, const QString& password);
|
Q_INVOKABLE void signup(const QString& email, const QString& username, const QString& password);
|
||||||
|
|
||||||
Q_INVOKABLE void openUrl(const QString& url) const;
|
Q_INVOKABLE void openUrl(const QString& url) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_LoginDialog_h
|
#endif // hifi_LoginDialog_h
|
||||||
|
|
|
@ -106,6 +106,10 @@ extern std::atomic<size_t> DECIMATED_TEXTURE_COUNT;
|
||||||
extern std::atomic<size_t> RECTIFIED_TEXTURE_COUNT;
|
extern std::atomic<size_t> RECTIFIED_TEXTURE_COUNT;
|
||||||
|
|
||||||
void Stats::updateStats(bool force) {
|
void Stats::updateStats(bool force) {
|
||||||
|
|
||||||
|
if (qApp->isInterstitialMode()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
QQuickItem* parent = parentItem();
|
QQuickItem* parent = parentItem();
|
||||||
if (!force) {
|
if (!force) {
|
||||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::Stats)) {
|
if (!Menu::getInstance()->isOptionChecked(MenuOption::Stats)) {
|
||||||
|
|
|
@ -305,6 +305,16 @@ void AudioClient::audioMixerKilled() {
|
||||||
emit disconnected();
|
emit disconnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AudioClient::setAudioPaused(bool pause) {
|
||||||
|
if (_audioPaused != pause) {
|
||||||
|
_audioPaused = pause;
|
||||||
|
|
||||||
|
if (!_audioPaused) {
|
||||||
|
negotiateAudioFormat();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QAudioDeviceInfo getNamedAudioDeviceForMode(QAudio::Mode mode, const QString& deviceName) {
|
QAudioDeviceInfo getNamedAudioDeviceForMode(QAudio::Mode mode, const QString& deviceName) {
|
||||||
QAudioDeviceInfo result;
|
QAudioDeviceInfo result;
|
||||||
foreach(QAudioDeviceInfo audioDevice, getAvailableDevices(mode)) {
|
foreach(QAudioDeviceInfo audioDevice, getAvailableDevices(mode)) {
|
||||||
|
@ -651,7 +661,6 @@ void AudioClient::stop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioClient::handleAudioEnvironmentDataPacket(QSharedPointer<ReceivedMessage> message) {
|
void AudioClient::handleAudioEnvironmentDataPacket(QSharedPointer<ReceivedMessage> message) {
|
||||||
|
|
||||||
char bitset;
|
char bitset;
|
||||||
message->readPrimitive(&bitset);
|
message->readPrimitive(&bitset);
|
||||||
|
|
||||||
|
@ -664,11 +673,10 @@ void AudioClient::handleAudioEnvironmentDataPacket(QSharedPointer<ReceivedMessag
|
||||||
_receivedAudioStream.setReverb(reverbTime, wetLevel);
|
_receivedAudioStream.setReverb(reverbTime, wetLevel);
|
||||||
} else {
|
} else {
|
||||||
_receivedAudioStream.clearReverb();
|
_receivedAudioStream.clearReverb();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioClient::handleAudioDataPacket(QSharedPointer<ReceivedMessage> message) {
|
void AudioClient::handleAudioDataPacket(QSharedPointer<ReceivedMessage> message) {
|
||||||
|
|
||||||
if (message->getType() == PacketType::SilentAudioFrame) {
|
if (message->getType() == PacketType::SilentAudioFrame) {
|
||||||
_silentInbound.increment();
|
_silentInbound.increment();
|
||||||
} else {
|
} else {
|
||||||
|
@ -1026,80 +1034,82 @@ void AudioClient::handleLocalEchoAndReverb(QByteArray& inputByteArray) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioClient::handleAudioInput(QByteArray& audioBuffer) {
|
void AudioClient::handleAudioInput(QByteArray& audioBuffer) {
|
||||||
if (_muted) {
|
if (!_audioPaused) {
|
||||||
_lastInputLoudness = 0.0f;
|
if (_muted) {
|
||||||
_timeSinceLastClip = 0.0f;
|
_lastInputLoudness = 0.0f;
|
||||||
} else {
|
|
||||||
int16_t* samples = reinterpret_cast<int16_t*>(audioBuffer.data());
|
|
||||||
int numSamples = audioBuffer.size() / AudioConstants::SAMPLE_SIZE;
|
|
||||||
int numFrames = numSamples / (_isStereoInput ? AudioConstants::STEREO : AudioConstants::MONO);
|
|
||||||
|
|
||||||
if (_isNoiseGateEnabled) {
|
|
||||||
// The audio gate includes DC removal
|
|
||||||
_audioGate->render(samples, samples, numFrames);
|
|
||||||
} else {
|
|
||||||
_audioGate->removeDC(samples, samples, numFrames);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t loudness = 0;
|
|
||||||
assert(numSamples < 65536); // int32_t loudness cannot overflow
|
|
||||||
bool didClip = false;
|
|
||||||
for (int i = 0; i < numSamples; ++i) {
|
|
||||||
const int32_t CLIPPING_THRESHOLD = (int32_t)(AudioConstants::MAX_SAMPLE_VALUE * 0.9f);
|
|
||||||
int32_t sample = std::abs((int32_t)samples[i]);
|
|
||||||
loudness += sample;
|
|
||||||
didClip |= (sample > CLIPPING_THRESHOLD);
|
|
||||||
}
|
|
||||||
_lastInputLoudness = (float)loudness / numSamples;
|
|
||||||
|
|
||||||
if (didClip) {
|
|
||||||
_timeSinceLastClip = 0.0f;
|
_timeSinceLastClip = 0.0f;
|
||||||
} else if (_timeSinceLastClip >= 0.0f) {
|
} else {
|
||||||
_timeSinceLastClip += (float)numSamples / (float)AudioConstants::SAMPLE_RATE;
|
int16_t* samples = reinterpret_cast<int16_t*>(audioBuffer.data());
|
||||||
|
int numSamples = audioBuffer.size() / AudioConstants::SAMPLE_SIZE;
|
||||||
|
int numFrames = numSamples / (_isStereoInput ? AudioConstants::STEREO : AudioConstants::MONO);
|
||||||
|
|
||||||
|
if (_isNoiseGateEnabled) {
|
||||||
|
// The audio gate includes DC removal
|
||||||
|
_audioGate->render(samples, samples, numFrames);
|
||||||
|
} else {
|
||||||
|
_audioGate->removeDC(samples, samples, numFrames);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t loudness = 0;
|
||||||
|
assert(numSamples < 65536); // int32_t loudness cannot overflow
|
||||||
|
bool didClip = false;
|
||||||
|
for (int i = 0; i < numSamples; ++i) {
|
||||||
|
const int32_t CLIPPING_THRESHOLD = (int32_t)(AudioConstants::MAX_SAMPLE_VALUE * 0.9f);
|
||||||
|
int32_t sample = std::abs((int32_t)samples[i]);
|
||||||
|
loudness += sample;
|
||||||
|
didClip |= (sample > CLIPPING_THRESHOLD);
|
||||||
|
}
|
||||||
|
_lastInputLoudness = (float)loudness / numSamples;
|
||||||
|
|
||||||
|
if (didClip) {
|
||||||
|
_timeSinceLastClip = 0.0f;
|
||||||
|
} else if (_timeSinceLastClip >= 0.0f) {
|
||||||
|
_timeSinceLastClip += (float)numSamples / (float)AudioConstants::SAMPLE_RATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit inputReceived(audioBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
emit inputReceived(audioBuffer);
|
emit inputLoudnessChanged(_lastInputLoudness);
|
||||||
|
|
||||||
|
// state machine to detect gate opening and closing
|
||||||
|
bool audioGateOpen = (_lastInputLoudness != 0.0f);
|
||||||
|
bool openedInLastBlock = !_audioGateOpen && audioGateOpen; // the gate just opened
|
||||||
|
bool closedInLastBlock = _audioGateOpen && !audioGateOpen; // the gate just closed
|
||||||
|
_audioGateOpen = audioGateOpen;
|
||||||
|
|
||||||
|
if (openedInLastBlock) {
|
||||||
|
emit noiseGateOpened();
|
||||||
|
} else if (closedInLastBlock) {
|
||||||
|
emit noiseGateClosed();
|
||||||
|
}
|
||||||
|
|
||||||
|
// the codec must be flushed to silence before sending silent packets,
|
||||||
|
// so delay the transition to silent packets by one packet after becoming silent.
|
||||||
|
auto packetType = _shouldEchoToServer ? PacketType::MicrophoneAudioWithEcho : PacketType::MicrophoneAudioNoEcho;
|
||||||
|
if (!audioGateOpen && !closedInLastBlock) {
|
||||||
|
packetType = PacketType::SilentAudioFrame;
|
||||||
|
_silentOutbound.increment();
|
||||||
|
} else {
|
||||||
|
_audioOutbound.increment();
|
||||||
|
}
|
||||||
|
|
||||||
|
Transform audioTransform;
|
||||||
|
audioTransform.setTranslation(_positionGetter());
|
||||||
|
audioTransform.setRotation(_orientationGetter());
|
||||||
|
|
||||||
|
QByteArray encodedBuffer;
|
||||||
|
if (_encoder) {
|
||||||
|
_encoder->encode(audioBuffer, encodedBuffer);
|
||||||
|
} else {
|
||||||
|
encodedBuffer = audioBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
emitAudioPacket(encodedBuffer.data(), encodedBuffer.size(), _outgoingAvatarAudioSequenceNumber, _isStereoInput,
|
||||||
|
audioTransform, avatarBoundingBoxCorner, avatarBoundingBoxScale,
|
||||||
|
packetType, _selectedCodecName);
|
||||||
|
_stats.sentPacket();
|
||||||
}
|
}
|
||||||
|
|
||||||
emit inputLoudnessChanged(_lastInputLoudness);
|
|
||||||
|
|
||||||
// state machine to detect gate opening and closing
|
|
||||||
bool audioGateOpen = (_lastInputLoudness != 0.0f);
|
|
||||||
bool openedInLastBlock = !_audioGateOpen && audioGateOpen; // the gate just opened
|
|
||||||
bool closedInLastBlock = _audioGateOpen && !audioGateOpen; // the gate just closed
|
|
||||||
_audioGateOpen = audioGateOpen;
|
|
||||||
|
|
||||||
if (openedInLastBlock) {
|
|
||||||
emit noiseGateOpened();
|
|
||||||
} else if (closedInLastBlock) {
|
|
||||||
emit noiseGateClosed();
|
|
||||||
}
|
|
||||||
|
|
||||||
// the codec must be flushed to silence before sending silent packets,
|
|
||||||
// so delay the transition to silent packets by one packet after becoming silent.
|
|
||||||
auto packetType = _shouldEchoToServer ? PacketType::MicrophoneAudioWithEcho : PacketType::MicrophoneAudioNoEcho;
|
|
||||||
if (!audioGateOpen && !closedInLastBlock) {
|
|
||||||
packetType = PacketType::SilentAudioFrame;
|
|
||||||
_silentOutbound.increment();
|
|
||||||
} else {
|
|
||||||
_audioOutbound.increment();
|
|
||||||
}
|
|
||||||
|
|
||||||
Transform audioTransform;
|
|
||||||
audioTransform.setTranslation(_positionGetter());
|
|
||||||
audioTransform.setRotation(_orientationGetter());
|
|
||||||
|
|
||||||
QByteArray encodedBuffer;
|
|
||||||
if (_encoder) {
|
|
||||||
_encoder->encode(audioBuffer, encodedBuffer);
|
|
||||||
} else {
|
|
||||||
encodedBuffer = audioBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
emitAudioPacket(encodedBuffer.data(), encodedBuffer.size(), _outgoingAvatarAudioSequenceNumber, _isStereoInput,
|
|
||||||
audioTransform, avatarBoundingBoxCorner, avatarBoundingBoxScale,
|
|
||||||
packetType, _selectedCodecName);
|
|
||||||
_stats.sentPacket();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioClient::handleMicAudioInput() {
|
void AudioClient::handleMicAudioInput() {
|
||||||
|
|
|
@ -162,6 +162,7 @@ public:
|
||||||
|
|
||||||
bool startRecording(const QString& filename);
|
bool startRecording(const QString& filename);
|
||||||
void stopRecording();
|
void stopRecording();
|
||||||
|
void setAudioPaused(bool pause);
|
||||||
|
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
|
@ -416,6 +417,7 @@ private:
|
||||||
QVector<AudioInjectorPointer> _activeLocalAudioInjectors;
|
QVector<AudioInjectorPointer> _activeLocalAudioInjectors;
|
||||||
|
|
||||||
bool _isPlayingBackRecording { false };
|
bool _isPlayingBackRecording { false };
|
||||||
|
bool _audioPaused { false };
|
||||||
|
|
||||||
CodecPluginPointer _codec;
|
CodecPluginPointer _codec;
|
||||||
QString _selectedCodecName;
|
QString _selectedCodecName;
|
||||||
|
|
|
@ -126,6 +126,8 @@ Avatar::Avatar(QThread* thread) :
|
||||||
_leftPointerGeometryID = geometryCache->allocateID();
|
_leftPointerGeometryID = geometryCache->allocateID();
|
||||||
_rightPointerGeometryID = geometryCache->allocateID();
|
_rightPointerGeometryID = geometryCache->allocateID();
|
||||||
_lastRenderUpdateTime = usecTimestampNow();
|
_lastRenderUpdateTime = usecTimestampNow();
|
||||||
|
|
||||||
|
indicateLoadingStatus(LoadingStatus::NoModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
Avatar::~Avatar() {
|
Avatar::~Avatar() {
|
||||||
|
@ -1370,12 +1372,15 @@ void Avatar::scaleVectorRelativeToPosition(glm::vec3 &positionToScale) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
void Avatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
||||||
if (!isMyAvatar()) {
|
|
||||||
createOrb();
|
|
||||||
}
|
|
||||||
AvatarData::setSkeletonModelURL(skeletonModelURL);
|
AvatarData::setSkeletonModelURL(skeletonModelURL);
|
||||||
if (QThread::currentThread() == thread()) {
|
if (QThread::currentThread() == thread()) {
|
||||||
|
|
||||||
|
if (!isMyAvatar()) {
|
||||||
|
createOrb();
|
||||||
|
}
|
||||||
|
|
||||||
_skeletonModel->setURL(_skeletonModelURL);
|
_skeletonModel->setURL(_skeletonModelURL);
|
||||||
|
indicateLoadingStatus(LoadingStatus::LoadModel);
|
||||||
} else {
|
} else {
|
||||||
QMetaObject::invokeMethod(_skeletonModel.get(), "setURL", Qt::QueuedConnection, Q_ARG(QUrl, _skeletonModelURL));
|
QMetaObject::invokeMethod(_skeletonModel.get(), "setURL", Qt::QueuedConnection, Q_ARG(QUrl, _skeletonModelURL));
|
||||||
}
|
}
|
||||||
|
@ -1388,11 +1393,12 @@ void Avatar::setModelURLFinished(bool success) {
|
||||||
_reconstructSoftEntitiesJointMap = true;
|
_reconstructSoftEntitiesJointMap = true;
|
||||||
|
|
||||||
if (!success && _skeletonModelURL != AvatarData::defaultFullAvatarModelUrl()) {
|
if (!success && _skeletonModelURL != AvatarData::defaultFullAvatarModelUrl()) {
|
||||||
|
indicateLoadingStatus(LoadingStatus::LoadFailure);
|
||||||
const int MAX_SKELETON_DOWNLOAD_ATTEMPTS = 4; // NOTE: we don't want to be as generous as ResourceCache is, we only want 4 attempts
|
const int MAX_SKELETON_DOWNLOAD_ATTEMPTS = 4; // NOTE: we don't want to be as generous as ResourceCache is, we only want 4 attempts
|
||||||
if (_skeletonModel->getResourceDownloadAttemptsRemaining() <= 0 ||
|
if (_skeletonModel->getResourceDownloadAttemptsRemaining() <= 0 ||
|
||||||
_skeletonModel->getResourceDownloadAttempts() > MAX_SKELETON_DOWNLOAD_ATTEMPTS) {
|
_skeletonModel->getResourceDownloadAttempts() > MAX_SKELETON_DOWNLOAD_ATTEMPTS) {
|
||||||
qCWarning(avatars_renderer) << "Using default after failing to load Avatar model: " << _skeletonModelURL
|
qCWarning(avatars_renderer) << "Using default after failing to load Avatar model: " << _skeletonModelURL
|
||||||
<< "after" << _skeletonModel->getResourceDownloadAttempts() << "attempts.";
|
<< "after" << _skeletonModel->getResourceDownloadAttempts() << "attempts.";
|
||||||
// call _skeletonModel.setURL, but leave our copy of _skeletonModelURL alone. This is so that
|
// call _skeletonModel.setURL, but leave our copy of _skeletonModelURL alone. This is so that
|
||||||
// we don't redo this every time we receive an identity packet from the avatar with the bad url.
|
// we don't redo this every time we receive an identity packet from the avatar with the bad url.
|
||||||
QMetaObject::invokeMethod(_skeletonModel.get(), "setURL",
|
QMetaObject::invokeMethod(_skeletonModel.get(), "setURL",
|
||||||
|
@ -1403,6 +1409,9 @@ void Avatar::setModelURLFinished(bool success) {
|
||||||
<< "out of:" << MAX_SKELETON_DOWNLOAD_ATTEMPTS;
|
<< "out of:" << MAX_SKELETON_DOWNLOAD_ATTEMPTS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (success) {
|
||||||
|
indicateLoadingStatus(LoadingStatus::LoadSuccess);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// rig is ready
|
// rig is ready
|
||||||
|
|
|
@ -107,6 +107,14 @@ public:
|
||||||
virtual bool isMyAvatar() const override { return false; }
|
virtual bool isMyAvatar() const override { return false; }
|
||||||
virtual void createOrb() { }
|
virtual void createOrb() { }
|
||||||
|
|
||||||
|
enum class LoadingStatus {
|
||||||
|
NoModel,
|
||||||
|
LoadModel,
|
||||||
|
LoadSuccess,
|
||||||
|
LoadFailure
|
||||||
|
};
|
||||||
|
virtual void indicateLoadingStatus(LoadingStatus loadingStatus) { _loadingStatus = loadingStatus; }
|
||||||
|
|
||||||
virtual QVector<glm::quat> getJointRotations() const override;
|
virtual QVector<glm::quat> getJointRotations() const override;
|
||||||
using AvatarData::getJointRotation;
|
using AvatarData::getJointRotation;
|
||||||
virtual glm::quat getJointRotation(int index) const override;
|
virtual glm::quat getJointRotation(int index) const override;
|
||||||
|
@ -540,6 +548,8 @@ protected:
|
||||||
static const float MYAVATAR_LOADING_PRIORITY;
|
static const float MYAVATAR_LOADING_PRIORITY;
|
||||||
static const float OTHERAVATAR_LOADING_PRIORITY;
|
static const float OTHERAVATAR_LOADING_PRIORITY;
|
||||||
static const float ATTACHMENT_LOADING_PRIORITY;
|
static const float ATTACHMENT_LOADING_PRIORITY;
|
||||||
|
|
||||||
|
LoadingStatus _loadingStatus { LoadingStatus::NoModel };
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_Avatar_h
|
#endif // hifi_Avatar_h
|
||||||
|
|
|
@ -113,6 +113,12 @@ AvatarHashMap::AvatarHashMap() {
|
||||||
packetReceiver.registerListener(PacketType::BulkAvatarTraits, this, "processBulkAvatarTraits");
|
packetReceiver.registerListener(PacketType::BulkAvatarTraits, this, "processBulkAvatarTraits");
|
||||||
|
|
||||||
connect(nodeList.data(), &NodeList::uuidChanged, this, &AvatarHashMap::sessionUUIDChanged);
|
connect(nodeList.data(), &NodeList::uuidChanged, this, &AvatarHashMap::sessionUUIDChanged);
|
||||||
|
|
||||||
|
connect(nodeList.data(), &NodeList::nodeKilled, this, [this](SharedNodePointer killedNode){
|
||||||
|
if (killedNode->getType() == NodeType::AvatarMixer) {
|
||||||
|
clearOtherAvatars();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<QUuid> AvatarHashMap::getAvatarIdentifiers() {
|
QVector<QUuid> AvatarHashMap::getAvatarIdentifiers() {
|
||||||
|
@ -429,3 +435,12 @@ void AvatarHashMap::sessionUUIDChanged(const QUuid& sessionUUID, const QUuid& ol
|
||||||
emit avatarSessionChangedEvent(sessionUUID, oldUUID);
|
emit avatarSessionChangedEvent(sessionUUID, oldUUID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AvatarHashMap::clearOtherAvatars() {
|
||||||
|
QWriteLocker locker(&_hashLock);
|
||||||
|
|
||||||
|
for (auto& av : _avatarHash) {
|
||||||
|
handleRemovedAvatar(av);
|
||||||
|
}
|
||||||
|
|
||||||
|
_avatarHash.clear();
|
||||||
|
}
|
||||||
|
|
|
@ -101,6 +101,8 @@ public:
|
||||||
void setReplicaCount(int count);
|
void setReplicaCount(int count);
|
||||||
int getReplicaCount() { return _replicas.getReplicaCount(); };
|
int getReplicaCount() { return _replicas.getReplicaCount(); };
|
||||||
|
|
||||||
|
virtual void clearOtherAvatars();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
|
|
|
@ -1297,9 +1297,20 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Check for removal
|
|
||||||
ModelPointer model;
|
ModelPointer model;
|
||||||
withReadLock([&] { model = _model; });
|
withReadLock([&] { model = _model; });
|
||||||
|
|
||||||
|
withWriteLock([&] {
|
||||||
|
bool visuallyReady = true;
|
||||||
|
if (_hasModel) {
|
||||||
|
if (model && _didLastVisualGeometryRequestSucceed) {
|
||||||
|
visuallyReady = (_prevModelLoaded && _texturesLoaded);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
entity->setVisuallyReady(visuallyReady);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check for removal
|
||||||
if (!_hasModel) {
|
if (!_hasModel) {
|
||||||
if (model) {
|
if (model) {
|
||||||
model->removeFromScene(scene, transaction);
|
model->removeFromScene(scene, transaction);
|
||||||
|
@ -1441,11 +1452,11 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
||||||
// That is where _currentFrame and _lastAnimated were updated.
|
// That is where _currentFrame and _lastAnimated were updated.
|
||||||
if (_animating) {
|
if (_animating) {
|
||||||
DETAILED_PROFILE_RANGE(simulation_physics, "Animate");
|
DETAILED_PROFILE_RANGE(simulation_physics, "Animate");
|
||||||
|
|
||||||
if (!jointsMapped()) {
|
if (!jointsMapped()) {
|
||||||
mapJoints(entity, model->getJointNames());
|
mapJoints(entity, model->getJointNames());
|
||||||
//else the joint have been mapped before but we have a new animation to load
|
//else the joint have been mapped before but we have a new animation to load
|
||||||
} else if (_animation && (_animation->getURL().toString() != entity->getAnimationURL())) {
|
} else if (_animation && (_animation->getURL().toString() != entity->getAnimationURL())) {
|
||||||
_animation = DependencyManager::get<AnimationCache>()->getAnimation(entity->getAnimationURL());
|
_animation = DependencyManager::get<AnimationCache>()->getAnimation(entity->getAnimationURL());
|
||||||
_jointMappingCompleted = false;
|
_jointMappingCompleted = false;
|
||||||
mapJoints(entity, model->getJointNames());
|
mapJoints(entity, model->getJointNames());
|
||||||
|
|
|
@ -288,6 +288,17 @@ void ZoneEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scen
|
||||||
updateHazeFromEntity(entity);
|
updateHazeFromEntity(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool visuallyReady = true;
|
||||||
|
uint32_t skyboxMode = entity->getSkyboxMode();
|
||||||
|
if (skyboxMode == COMPONENT_MODE_ENABLED && !_skyboxTextureURL.isEmpty()) {
|
||||||
|
bool skyboxLoadedOrFailed = (_skyboxTexture && (_skyboxTexture->isLoaded() || _skyboxTexture->isFailed()));
|
||||||
|
|
||||||
|
visuallyReady = skyboxLoadedOrFailed;
|
||||||
|
}
|
||||||
|
|
||||||
|
entity->setVisuallyReady(visuallyReady);
|
||||||
|
|
||||||
if (bloomChanged) {
|
if (bloomChanged) {
|
||||||
updateBloomFromEntity(entity);
|
updateBloomFromEntity(entity);
|
||||||
}
|
}
|
||||||
|
|
|
@ -305,6 +305,7 @@ public:
|
||||||
void setDynamic(bool value);
|
void setDynamic(bool value);
|
||||||
|
|
||||||
virtual bool shouldBePhysical() const { return false; }
|
virtual bool shouldBePhysical() const { return false; }
|
||||||
|
bool isVisuallyReady() const { return _visuallyReady; }
|
||||||
|
|
||||||
bool getLocked() const;
|
bool getLocked() const;
|
||||||
void setLocked(bool value);
|
void setLocked(bool value);
|
||||||
|
@ -527,6 +528,7 @@ public:
|
||||||
void removeCloneID(const QUuid& cloneID);
|
void removeCloneID(const QUuid& cloneID);
|
||||||
const QVector<QUuid> getCloneIDs() const;
|
const QVector<QUuid> getCloneIDs() const;
|
||||||
void setCloneIDs(const QVector<QUuid>& cloneIDs);
|
void setCloneIDs(const QVector<QUuid>& cloneIDs);
|
||||||
|
void setVisuallyReady(bool visuallyReady) { _visuallyReady = visuallyReady; }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void requestRenderUpdate();
|
void requestRenderUpdate();
|
||||||
|
@ -639,6 +641,7 @@ protected:
|
||||||
EntityTreeElementPointer _element; // set by EntityTreeElement
|
EntityTreeElementPointer _element; // set by EntityTreeElement
|
||||||
void* _physicsInfo { nullptr }; // set by EntitySimulation
|
void* _physicsInfo { nullptr }; // set by EntitySimulation
|
||||||
bool _simulated { false }; // set by EntitySimulation
|
bool _simulated { false }; // set by EntitySimulation
|
||||||
|
bool _visuallyReady { true };
|
||||||
|
|
||||||
bool addActionInternal(EntitySimulationPointer simulation, EntityDynamicPointer action);
|
bool addActionInternal(EntitySimulationPointer simulation, EntityDynamicPointer action);
|
||||||
bool removeActionInternal(const QUuid& actionID, EntitySimulationPointer simulation = nullptr);
|
bool removeActionInternal(const QUuid& actionID, EntitySimulationPointer simulation = nullptr);
|
||||||
|
|
|
@ -40,6 +40,7 @@ ModelEntityItem::ModelEntityItem(const EntityItemID& entityItemID) : EntityItem(
|
||||||
_type = EntityTypes::Model;
|
_type = EntityTypes::Model;
|
||||||
_lastKnownCurrentFrame = -1;
|
_lastKnownCurrentFrame = -1;
|
||||||
_color[0] = _color[1] = _color[2] = 0;
|
_color[0] = _color[1] = _color[2] = 0;
|
||||||
|
_visuallyReady = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString ModelEntityItem::getTextures() const {
|
const QString ModelEntityItem::getTextures() const {
|
||||||
|
|
|
@ -42,6 +42,7 @@ ZoneEntityItem::ZoneEntityItem(const EntityItemID& entityItemID) : EntityItem(en
|
||||||
|
|
||||||
_shapeType = DEFAULT_SHAPE_TYPE;
|
_shapeType = DEFAULT_SHAPE_TYPE;
|
||||||
_compoundShapeURL = DEFAULT_COMPOUND_SHAPE_URL;
|
_compoundShapeURL = DEFAULT_COMPOUND_SHAPE_URL;
|
||||||
|
_visuallyReady = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityItemProperties ZoneEntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
|
EntityItemProperties ZoneEntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
|
||||||
|
|
|
@ -25,15 +25,15 @@ static bool timeElapsed = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void GLBackend::do_beginQuery(const Batch& batch, size_t paramOffset) {
|
void GLBackend::do_beginQuery(const Batch& batch, size_t paramOffset) {
|
||||||
#if !defined(USE_GLES)
|
|
||||||
auto query = batch._queries.get(batch._params[paramOffset]._uint);
|
auto query = batch._queries.get(batch._params[paramOffset]._uint);
|
||||||
GLQuery* glquery = syncGPUObject(*query);
|
GLQuery* glquery = syncGPUObject(*query);
|
||||||
if (glquery) {
|
if (glquery) {
|
||||||
PROFILE_RANGE_BEGIN(render_gpu_gl_detail, glquery->_profileRangeId, query->getName().c_str(), 0xFFFF7F00);
|
PROFILE_RANGE_BEGIN(render_gpu_gl_detail, glquery->_profileRangeId, query->getName().c_str(), 0xFFFF7F00);
|
||||||
|
|
||||||
++_queryStage._rangeQueryDepth;
|
++_queryStage._rangeQueryDepth;
|
||||||
glGetInteger64v(GL_TIMESTAMP, (GLint64*)&glquery->_batchElapsedTime);
|
glquery->_batchElapsedTimeBegin = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
|
#if !defined(USE_GLES)
|
||||||
if (timeElapsed) {
|
if (timeElapsed) {
|
||||||
if (_queryStage._rangeQueryDepth <= MAX_RANGE_QUERY_DEPTH) {
|
if (_queryStage._rangeQueryDepth <= MAX_RANGE_QUERY_DEPTH) {
|
||||||
glBeginQuery(GL_TIME_ELAPSED, glquery->_endqo);
|
glBeginQuery(GL_TIME_ELAPSED, glquery->_endqo);
|
||||||
|
@ -41,17 +41,18 @@ void GLBackend::do_beginQuery(const Batch& batch, size_t paramOffset) {
|
||||||
} else {
|
} else {
|
||||||
glQueryCounter(glquery->_beginqo, GL_TIMESTAMP);
|
glQueryCounter(glquery->_beginqo, GL_TIMESTAMP);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
glquery->_rangeQueryDepth = _queryStage._rangeQueryDepth;
|
glquery->_rangeQueryDepth = _queryStage._rangeQueryDepth;
|
||||||
(void)CHECK_GL_ERROR();
|
(void)CHECK_GL_ERROR();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLBackend::do_endQuery(const Batch& batch, size_t paramOffset) {
|
void GLBackend::do_endQuery(const Batch& batch, size_t paramOffset) {
|
||||||
#if !defined(USE_GLES)
|
|
||||||
auto query = batch._queries.get(batch._params[paramOffset]._uint);
|
auto query = batch._queries.get(batch._params[paramOffset]._uint);
|
||||||
GLQuery* glquery = syncGPUObject(*query);
|
GLQuery* glquery = syncGPUObject(*query);
|
||||||
if (glquery) {
|
if (glquery) {
|
||||||
|
#if !defined(USE_GLES)
|
||||||
if (timeElapsed) {
|
if (timeElapsed) {
|
||||||
if (_queryStage._rangeQueryDepth <= MAX_RANGE_QUERY_DEPTH) {
|
if (_queryStage._rangeQueryDepth <= MAX_RANGE_QUERY_DEPTH) {
|
||||||
glEndQuery(GL_TIME_ELAPSED);
|
glEndQuery(GL_TIME_ELAPSED);
|
||||||
|
@ -59,27 +60,26 @@ void GLBackend::do_endQuery(const Batch& batch, size_t paramOffset) {
|
||||||
} else {
|
} else {
|
||||||
glQueryCounter(glquery->_endqo, GL_TIMESTAMP);
|
glQueryCounter(glquery->_endqo, GL_TIMESTAMP);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
--_queryStage._rangeQueryDepth;
|
--_queryStage._rangeQueryDepth;
|
||||||
GLint64 now;
|
auto duration_ns = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - glquery->_batchElapsedTimeBegin);
|
||||||
glGetInteger64v(GL_TIMESTAMP, &now);
|
glquery->_batchElapsedTime = duration_ns.count();
|
||||||
glquery->_batchElapsedTime = now - glquery->_batchElapsedTime;
|
|
||||||
|
|
||||||
PROFILE_RANGE_END(render_gpu_gl_detail, glquery->_profileRangeId);
|
PROFILE_RANGE_END(render_gpu_gl_detail, glquery->_profileRangeId);
|
||||||
|
|
||||||
(void)CHECK_GL_ERROR();
|
(void)CHECK_GL_ERROR();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLBackend::do_getQuery(const Batch& batch, size_t paramOffset) {
|
void GLBackend::do_getQuery(const Batch& batch, size_t paramOffset) {
|
||||||
#if !defined(USE_GLES)
|
|
||||||
auto query = batch._queries.get(batch._params[paramOffset]._uint);
|
auto query = batch._queries.get(batch._params[paramOffset]._uint);
|
||||||
GLQuery* glquery = syncGPUObject(*query);
|
GLQuery* glquery = syncGPUObject(*query);
|
||||||
if (glquery) {
|
if (glquery) {
|
||||||
if (glquery->_rangeQueryDepth > MAX_RANGE_QUERY_DEPTH) {
|
if (glquery->_rangeQueryDepth > MAX_RANGE_QUERY_DEPTH) {
|
||||||
query->triggerReturnHandler(glquery->_result, glquery->_batchElapsedTime);
|
query->triggerReturnHandler(glquery->_result, glquery->_batchElapsedTime);
|
||||||
} else {
|
} else {
|
||||||
|
#if !defined(USE_GLES)
|
||||||
glGetQueryObjectui64v(glquery->_endqo, GL_QUERY_RESULT_AVAILABLE, &glquery->_result);
|
glGetQueryObjectui64v(glquery->_endqo, GL_QUERY_RESULT_AVAILABLE, &glquery->_result);
|
||||||
if (glquery->_result == GL_TRUE) {
|
if (glquery->_result == GL_TRUE) {
|
||||||
if (timeElapsed) {
|
if (timeElapsed) {
|
||||||
|
@ -92,10 +92,13 @@ void GLBackend::do_getQuery(const Batch& batch, size_t paramOffset) {
|
||||||
}
|
}
|
||||||
query->triggerReturnHandler(glquery->_result, glquery->_batchElapsedTime);
|
query->triggerReturnHandler(glquery->_result, glquery->_batchElapsedTime);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
// gles3 is not supporting true time query returns just the batch elapsed time
|
||||||
|
query->triggerReturnHandler(0, glquery->_batchElapsedTime);
|
||||||
|
#endif
|
||||||
(void)CHECK_GL_ERROR();
|
(void)CHECK_GL_ERROR();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLBackend::resetQueryStage() {
|
void GLBackend::resetQueryStage() {
|
||||||
|
|
|
@ -47,8 +47,9 @@ public:
|
||||||
|
|
||||||
const GLuint& _endqo = { _id };
|
const GLuint& _endqo = { _id };
|
||||||
const GLuint _beginqo = { 0 };
|
const GLuint _beginqo = { 0 };
|
||||||
GLuint64 _result { (GLuint64)-1 };
|
GLuint64 _result { (GLuint64)0 };
|
||||||
GLuint64 _batchElapsedTime { (GLuint64) 0 };
|
GLuint64 _batchElapsedTime{ (GLuint64)0 };
|
||||||
|
std::chrono::high_resolution_clock::time_point _batchElapsedTimeBegin;
|
||||||
uint64_t _profileRangeId { 0 };
|
uint64_t _profileRangeId { 0 };
|
||||||
uint32_t _rangeQueryDepth { 0 };
|
uint32_t _rangeQueryDepth { 0 };
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "udt/PacketHeaders.h"
|
#include "udt/PacketHeaders.h"
|
||||||
|
|
||||||
const QString DEFAULT_HIFI_ADDRESS = "file:///~/serverless/tutorial.json";
|
const QString DEFAULT_HIFI_ADDRESS = "file:///~/serverless/tutorial.json";
|
||||||
|
const QString REDIRECT_HIFI_ADDRESS = "file:///~/serverless/redirect.json";
|
||||||
const QString ADDRESS_MANAGER_SETTINGS_GROUP = "AddressManager";
|
const QString ADDRESS_MANAGER_SETTINGS_GROUP = "AddressManager";
|
||||||
const QString SETTINGS_CURRENT_ADDRESS_KEY = "address";
|
const QString SETTINGS_CURRENT_ADDRESS_KEY = "address";
|
||||||
|
|
||||||
|
@ -111,6 +112,9 @@ QUrl AddressManager::currentFacingPublicAddress() const {
|
||||||
return shareableAddress;
|
return shareableAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QUrl AddressManager::lastAddress() const {
|
||||||
|
return _lastVisitedURL;
|
||||||
|
}
|
||||||
|
|
||||||
void AddressManager::loadSettings(const QString& lookupString) {
|
void AddressManager::loadSettings(const QString& lookupString) {
|
||||||
#if defined(USE_GLES) && defined(Q_OS_WIN)
|
#if defined(USE_GLES) && defined(Q_OS_WIN)
|
||||||
|
@ -247,9 +251,12 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl, LookupTrigger trigger) {
|
||||||
|
|
||||||
UserActivityLogger::getInstance().wentTo(trigger, URL_TYPE_USER, lookupUrl.toString());
|
UserActivityLogger::getInstance().wentTo(trigger, URL_TYPE_USER, lookupUrl.toString());
|
||||||
|
|
||||||
|
// save the last visited domain URL.
|
||||||
|
_lastVisitedURL = lookupUrl;
|
||||||
|
|
||||||
// in case we're failing to connect to where we thought this user was
|
// in case we're failing to connect to where we thought this user was
|
||||||
// store their username as previous lookup so we can refresh their location via API
|
// store their username as previous lookup so we can refresh their location via API
|
||||||
_previousLookup = lookupUrl;
|
_previousAPILookup = lookupUrl;
|
||||||
} else {
|
} else {
|
||||||
// we're assuming this is either a network address or global place name
|
// we're assuming this is either a network address or global place name
|
||||||
// check if it is a network address first
|
// check if it is a network address first
|
||||||
|
@ -259,8 +266,11 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl, LookupTrigger trigger) {
|
||||||
|
|
||||||
UserActivityLogger::getInstance().wentTo(trigger, URL_TYPE_NETWORK_ADDRESS, lookupUrl.toString());
|
UserActivityLogger::getInstance().wentTo(trigger, URL_TYPE_NETWORK_ADDRESS, lookupUrl.toString());
|
||||||
|
|
||||||
|
// save the last visited domain URL.
|
||||||
|
_lastVisitedURL = lookupUrl;
|
||||||
|
|
||||||
// a network address lookup clears the previous lookup since we don't expect to re-attempt it
|
// a network address lookup clears the previous lookup since we don't expect to re-attempt it
|
||||||
_previousLookup.clear();
|
_previousAPILookup.clear();
|
||||||
|
|
||||||
// If the host changed then we have already saved to history
|
// If the host changed then we have already saved to history
|
||||||
if (hostChanged) {
|
if (hostChanged) {
|
||||||
|
@ -278,8 +288,11 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl, LookupTrigger trigger) {
|
||||||
} else if (handleDomainID(lookupUrl.host())){
|
} else if (handleDomainID(lookupUrl.host())){
|
||||||
UserActivityLogger::getInstance().wentTo(trigger, URL_TYPE_DOMAIN_ID, lookupUrl.toString());
|
UserActivityLogger::getInstance().wentTo(trigger, URL_TYPE_DOMAIN_ID, lookupUrl.toString());
|
||||||
|
|
||||||
|
// save the last visited domain URL.
|
||||||
|
_lastVisitedURL = lookupUrl;
|
||||||
|
|
||||||
// store this domain ID as the previous lookup in case we're failing to connect and want to refresh API info
|
// store this domain ID as the previous lookup in case we're failing to connect and want to refresh API info
|
||||||
_previousLookup = lookupUrl;
|
_previousAPILookup = lookupUrl;
|
||||||
|
|
||||||
// no place name - this is probably a domain ID
|
// no place name - this is probably a domain ID
|
||||||
// try to look up the domain ID on the metaverse API
|
// try to look up the domain ID on the metaverse API
|
||||||
|
@ -287,8 +300,11 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl, LookupTrigger trigger) {
|
||||||
} else {
|
} else {
|
||||||
UserActivityLogger::getInstance().wentTo(trigger, URL_TYPE_PLACE, lookupUrl.toString());
|
UserActivityLogger::getInstance().wentTo(trigger, URL_TYPE_PLACE, lookupUrl.toString());
|
||||||
|
|
||||||
|
// save the last visited domain URL.
|
||||||
|
_lastVisitedURL = lookupUrl;
|
||||||
|
|
||||||
// store this place name as the previous lookup in case we fail to connect and want to refresh API info
|
// store this place name as the previous lookup in case we fail to connect and want to refresh API info
|
||||||
_previousLookup = lookupUrl;
|
_previousAPILookup = lookupUrl;
|
||||||
|
|
||||||
// wasn't an address - lookup the place name
|
// wasn't an address - lookup the place name
|
||||||
// we may have a path that defines a relative viewpoint - pass that through the lookup so we can go to it after
|
// we may have a path that defines a relative viewpoint - pass that through the lookup so we can go to it after
|
||||||
|
@ -302,7 +318,7 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl, LookupTrigger trigger) {
|
||||||
qCDebug(networking) << "Going to relative path" << lookupUrl.path();
|
qCDebug(networking) << "Going to relative path" << lookupUrl.path();
|
||||||
|
|
||||||
// a path lookup clears the previous lookup since we don't expect to re-attempt it
|
// a path lookup clears the previous lookup since we don't expect to re-attempt it
|
||||||
_previousLookup.clear();
|
_previousAPILookup.clear();
|
||||||
|
|
||||||
// if this is a relative path then handle it as a relative viewpoint
|
// if this is a relative path then handle it as a relative viewpoint
|
||||||
handlePath(lookupUrl.path(), trigger, true);
|
handlePath(lookupUrl.path(), trigger, true);
|
||||||
|
@ -314,7 +330,10 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl, LookupTrigger trigger) {
|
||||||
// be loaded over http(s)
|
// be loaded over http(s)
|
||||||
// lookupUrl.scheme() == URL_SCHEME_HTTP ||
|
// lookupUrl.scheme() == URL_SCHEME_HTTP ||
|
||||||
// lookupUrl.scheme() == URL_SCHEME_HTTPS ||
|
// lookupUrl.scheme() == URL_SCHEME_HTTPS ||
|
||||||
_previousLookup.clear();
|
// TODO once a file can return a connection refusal if there were to be some kind of load error, we'd
|
||||||
|
// need to store the previous domain tried in _lastVisitedURL. For now , do not store it.
|
||||||
|
|
||||||
|
_previousAPILookup.clear();
|
||||||
_shareablePlaceName.clear();
|
_shareablePlaceName.clear();
|
||||||
setDomainInfo(lookupUrl, trigger);
|
setDomainInfo(lookupUrl, trigger);
|
||||||
emit lookupResultsFinished();
|
emit lookupResultsFinished();
|
||||||
|
@ -381,7 +400,7 @@ void AddressManager::handleAPIResponse(QNetworkReply* requestReply) {
|
||||||
QJsonObject dataObject = responseObject["data"].toObject();
|
QJsonObject dataObject = responseObject["data"].toObject();
|
||||||
|
|
||||||
// Lookup succeeded, don't keep re-trying it (especially on server restarts)
|
// Lookup succeeded, don't keep re-trying it (especially on server restarts)
|
||||||
_previousLookup.clear();
|
_previousAPILookup.clear();
|
||||||
|
|
||||||
if (!dataObject.isEmpty()) {
|
if (!dataObject.isEmpty()) {
|
||||||
goToAddressFromObject(dataObject.toVariantMap(), requestReply);
|
goToAddressFromObject(dataObject.toVariantMap(), requestReply);
|
||||||
|
@ -547,7 +566,7 @@ void AddressManager::handleAPIError(QNetworkReply* errorReply) {
|
||||||
|
|
||||||
if (errorReply->error() == QNetworkReply::ContentNotFoundError) {
|
if (errorReply->error() == QNetworkReply::ContentNotFoundError) {
|
||||||
// if this is a lookup that has no result, don't keep re-trying it
|
// if this is a lookup that has no result, don't keep re-trying it
|
||||||
_previousLookup.clear();
|
_previousAPILookup.clear();
|
||||||
|
|
||||||
emit lookupResultIsNotFound();
|
emit lookupResultIsNotFound();
|
||||||
}
|
}
|
||||||
|
@ -709,7 +728,6 @@ bool AddressManager::handleViewpoint(const QString& viewpointString, bool should
|
||||||
// We use _newHostLookupPath to determine if the client has already stored its last address
|
// We use _newHostLookupPath to determine if the client has already stored its last address
|
||||||
// before moving to a new host thanks to the information in the same lookup URL.
|
// before moving to a new host thanks to the information in the same lookup URL.
|
||||||
|
|
||||||
|
|
||||||
if (definitelyPathOnly || (!pathString.isEmpty() && pathString != _newHostLookupPath)
|
if (definitelyPathOnly || (!pathString.isEmpty() && pathString != _newHostLookupPath)
|
||||||
|| trigger == Back || trigger == Forward) {
|
|| trigger == Back || trigger == Forward) {
|
||||||
addCurrentAddressToHistory(trigger);
|
addCurrentAddressToHistory(trigger);
|
||||||
|
@ -843,8 +861,8 @@ void AddressManager::goToUser(const QString& username, bool shouldMatchOrientati
|
||||||
|
|
||||||
void AddressManager::refreshPreviousLookup() {
|
void AddressManager::refreshPreviousLookup() {
|
||||||
// if we have a non-empty previous lookup, fire it again now (but don't re-store it in the history)
|
// if we have a non-empty previous lookup, fire it again now (but don't re-store it in the history)
|
||||||
if (!_previousLookup.isEmpty()) {
|
if (!_previousAPILookup.isEmpty()) {
|
||||||
handleUrl(_previousLookup, LookupTrigger::AttemptedRefresh);
|
handleUrl(_previousAPILookup, LookupTrigger::AttemptedRefresh);
|
||||||
} else {
|
} else {
|
||||||
handleUrl(currentAddress(), LookupTrigger::AttemptedRefresh);
|
handleUrl(currentAddress(), LookupTrigger::AttemptedRefresh);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "AccountManager.h"
|
#include "AccountManager.h"
|
||||||
|
|
||||||
extern const QString DEFAULT_HIFI_ADDRESS;
|
extern const QString DEFAULT_HIFI_ADDRESS;
|
||||||
|
extern const QString REDIRECT_HIFI_ADDRESS;
|
||||||
|
|
||||||
const QString SANDBOX_HIFI_ADDRESS = "hifi://localhost";
|
const QString SANDBOX_HIFI_ADDRESS = "hifi://localhost";
|
||||||
const QString INDEX_PATH = "/";
|
const QString INDEX_PATH = "/";
|
||||||
|
@ -55,7 +56,6 @@ const QString GET_PLACE = "/api/v1/places/%1";
|
||||||
* <em>Read-only.</em>
|
* <em>Read-only.</em>
|
||||||
* @property {boolean} isConnected - <code>true</code> if you're connected to the domain in your current <code>href</code>
|
* @property {boolean} isConnected - <code>true</code> if you're connected to the domain in your current <code>href</code>
|
||||||
* metaverse address, otherwise <code>false</code>.
|
* metaverse address, otherwise <code>false</code>.
|
||||||
* <em>Read-only.</em>
|
|
||||||
* @property {string} pathname - The location and orientation in your current <code>href</code> metaverse address
|
* @property {string} pathname - The location and orientation in your current <code>href</code> metaverse address
|
||||||
* (e.g., <code>"/15,-10,26/0,0,0,1"</code>).
|
* (e.g., <code>"/15,-10,26/0,0,0,1"</code>).
|
||||||
* <em>Read-only.</em>
|
* <em>Read-only.</em>
|
||||||
|
@ -140,7 +140,8 @@ public:
|
||||||
* </table>
|
* </table>
|
||||||
* @typedef {number} location.LookupTrigger
|
* @typedef {number} location.LookupTrigger
|
||||||
*/
|
*/
|
||||||
enum LookupTrigger {
|
enum LookupTrigger
|
||||||
|
{
|
||||||
UserInput,
|
UserInput,
|
||||||
Back,
|
Back,
|
||||||
Forward,
|
Forward,
|
||||||
|
@ -164,6 +165,8 @@ public:
|
||||||
QString currentPath(bool withOrientation = true) const;
|
QString currentPath(bool withOrientation = true) const;
|
||||||
QString currentFacingPath() const;
|
QString currentFacingPath() const;
|
||||||
|
|
||||||
|
QUrl lastAddress() const;
|
||||||
|
|
||||||
const QUuid& getRootPlaceID() const { return _rootPlaceID; }
|
const QUuid& getRootPlaceID() const { return _rootPlaceID; }
|
||||||
QString getPlaceName() const;
|
QString getPlaceName() const;
|
||||||
QString getDomainID() const;
|
QString getDomainID() const;
|
||||||
|
@ -191,7 +194,7 @@ public slots:
|
||||||
* Helps ensure that user's location history is correctly maintained.
|
* Helps ensure that user's location history is correctly maintained.
|
||||||
*/
|
*/
|
||||||
void handleLookupString(const QString& lookupString, bool fromSuggestions = false);
|
void handleLookupString(const QString& lookupString, bool fromSuggestions = false);
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Go to a position and orientation resulting from a lookup for a named path in the domain (set in the domain server's
|
* Go to a position and orientation resulting from a lookup for a named path in the domain (set in the domain server's
|
||||||
* settings).
|
* settings).
|
||||||
|
@ -204,8 +207,9 @@ public slots:
|
||||||
// functions and signals that should be exposed are moved to a scripting interface class.
|
// functions and signals that should be exposed are moved to a scripting interface class.
|
||||||
//
|
//
|
||||||
// we currently expect this to be called from NodeList once handleLookupString has been called with a path
|
// we currently expect this to be called from NodeList once handleLookupString has been called with a path
|
||||||
bool goToViewpointForPath(const QString& viewpointString, const QString& pathString)
|
bool goToViewpointForPath(const QString& viewpointString, const QString& pathString) {
|
||||||
{ return handleViewpoint(viewpointString, false, DomainPathResponse, false, pathString); }
|
return handleViewpoint(viewpointString, false, DomainPathResponse, false, pathString);
|
||||||
|
}
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Go back to the previous location in your navigation history, if there is one.
|
* Go back to the previous location in your navigation history, if there is one.
|
||||||
|
@ -226,8 +230,10 @@ public slots:
|
||||||
* @param {location.LookupTrigger} trigger=StartupFromSettings - The reason for the function call. Helps ensure that user's
|
* @param {location.LookupTrigger} trigger=StartupFromSettings - The reason for the function call. Helps ensure that user's
|
||||||
* location history is correctly maintained.
|
* location history is correctly maintained.
|
||||||
*/
|
*/
|
||||||
void goToLocalSandbox(QString path = "", LookupTrigger trigger = LookupTrigger::StartupFromSettings) { handleUrl(SANDBOX_HIFI_ADDRESS + path, trigger); }
|
void goToLocalSandbox(QString path = "", LookupTrigger trigger = LookupTrigger::StartupFromSettings) {
|
||||||
|
handleUrl(SANDBOX_HIFI_ADDRESS + path, trigger);
|
||||||
|
}
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Go to the default "welcome" metaverse address.
|
* Go to the default "welcome" metaverse address.
|
||||||
* @function location.goToEntry
|
* @function location.goToEntry
|
||||||
|
@ -245,6 +251,12 @@ public slots:
|
||||||
*/
|
*/
|
||||||
void goToUser(const QString& username, bool shouldMatchOrientation = true);
|
void goToUser(const QString& username, bool shouldMatchOrientation = true);
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Go to the last address tried. This will be the last URL tried from location.handleLookupString
|
||||||
|
* @function location.goToLastAddress
|
||||||
|
*/
|
||||||
|
void goToLastAddress() { handleUrl(_lastVisitedURL, LookupTrigger::AttemptedRefresh); }
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Refresh the current address, e.g., after connecting to a domain in order to position the user to the desired location.
|
* Refresh the current address, e.g., after connecting to a domain in order to position the user to the desired location.
|
||||||
* @function location.refreshPreviousLookup
|
* @function location.refreshPreviousLookup
|
||||||
|
@ -352,7 +364,8 @@ signals:
|
||||||
* location.locationChangeRequired.connect(onLocationChangeRequired);
|
* location.locationChangeRequired.connect(onLocationChangeRequired);
|
||||||
*/
|
*/
|
||||||
void locationChangeRequired(const glm::vec3& newPosition,
|
void locationChangeRequired(const glm::vec3& newPosition,
|
||||||
bool hasOrientationChange, const glm::quat& newOrientation,
|
bool hasOrientationChange,
|
||||||
|
const glm::quat& newOrientation,
|
||||||
bool shouldFaceLocation);
|
bool shouldFaceLocation);
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
|
@ -423,7 +436,7 @@ private slots:
|
||||||
void handleShareableNameAPIResponse(QNetworkReply* requestReply);
|
void handleShareableNameAPIResponse(QNetworkReply* requestReply);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void goToAddressFromObject(const QVariantMap& addressMap, const QNetworkReply* reply);
|
void goToAddressFromObject(const QVariantMap& addressMap, const QNetworkReply* reply);
|
||||||
|
|
||||||
// Set host and port, and return `true` if it was changed.
|
// Set host and port, and return `true` if it was changed.
|
||||||
bool setHost(const QString& host, LookupTrigger trigger, quint16 port = 0);
|
bool setHost(const QString& host, LookupTrigger trigger, quint16 port = 0);
|
||||||
|
@ -435,8 +448,11 @@ private:
|
||||||
|
|
||||||
bool handleNetworkAddress(const QString& lookupString, LookupTrigger trigger, bool& hostChanged);
|
bool handleNetworkAddress(const QString& lookupString, LookupTrigger trigger, bool& hostChanged);
|
||||||
void handlePath(const QString& path, LookupTrigger trigger, bool wasPathOnly = false);
|
void handlePath(const QString& path, LookupTrigger trigger, bool wasPathOnly = false);
|
||||||
bool handleViewpoint(const QString& viewpointString, bool shouldFace, LookupTrigger trigger,
|
bool handleViewpoint(const QString& viewpointString,
|
||||||
bool definitelyPathOnly = false, const QString& pathString = QString());
|
bool shouldFace,
|
||||||
|
LookupTrigger trigger,
|
||||||
|
bool definitelyPathOnly = false,
|
||||||
|
const QString& pathString = QString());
|
||||||
bool handleUsername(const QString& lookupString);
|
bool handleUsername(const QString& lookupString);
|
||||||
bool handleDomainID(const QString& host);
|
bool handleDomainID(const QString& host);
|
||||||
|
|
||||||
|
@ -446,6 +462,7 @@ private:
|
||||||
void addCurrentAddressToHistory(LookupTrigger trigger);
|
void addCurrentAddressToHistory(LookupTrigger trigger);
|
||||||
|
|
||||||
QUrl _domainURL;
|
QUrl _domainURL;
|
||||||
|
QUrl _lastVisitedURL;
|
||||||
|
|
||||||
QUuid _rootPlaceID;
|
QUuid _rootPlaceID;
|
||||||
PositionGetter _positionGetter;
|
PositionGetter _positionGetter;
|
||||||
|
@ -459,7 +476,7 @@ private:
|
||||||
|
|
||||||
QString _newHostLookupPath;
|
QString _newHostLookupPath;
|
||||||
|
|
||||||
QUrl _previousLookup;
|
QUrl _previousAPILookup;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_AddressManager_h
|
#endif // hifi_AddressManager_h
|
||||||
|
|
|
@ -99,6 +99,7 @@ void DomainHandler::softReset() {
|
||||||
|
|
||||||
clearSettings();
|
clearSettings();
|
||||||
|
|
||||||
|
_isInErrorState = false;
|
||||||
_connectionDenialsSinceKeypairRegen = 0;
|
_connectionDenialsSinceKeypairRegen = 0;
|
||||||
_checkInPacketsSinceLastReply = 0;
|
_checkInPacketsSinceLastReply = 0;
|
||||||
|
|
||||||
|
@ -128,6 +129,11 @@ void DomainHandler::hardReset() {
|
||||||
_pendingPath.clear();
|
_pendingPath.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DomainHandler::setErrorDomainURL(const QUrl& url) {
|
||||||
|
_errorDomainURL = url;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
void DomainHandler::setSockAddr(const HifiSockAddr& sockAddr, const QString& hostname) {
|
void DomainHandler::setSockAddr(const HifiSockAddr& sockAddr, const QString& hostname) {
|
||||||
if (_sockAddr != sockAddr) {
|
if (_sockAddr != sockAddr) {
|
||||||
// we should reset on a sockAddr change
|
// we should reset on a sockAddr change
|
||||||
|
@ -171,7 +177,8 @@ void DomainHandler::setURLAndID(QUrl domainURL, QUuid domainID) {
|
||||||
domainPort = DEFAULT_DOMAIN_SERVER_PORT;
|
domainPort = DEFAULT_DOMAIN_SERVER_PORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_domainURL != domainURL || _sockAddr.getPort() != domainPort) {
|
// if it's in the error state, reset and try again.
|
||||||
|
if ((_domainURL != domainURL || _sockAddr.getPort() != domainPort) || _isInErrorState) {
|
||||||
// re-set the domain info so that auth information is reloaded
|
// re-set the domain info so that auth information is reloaded
|
||||||
hardReset();
|
hardReset();
|
||||||
|
|
||||||
|
@ -206,7 +213,8 @@ void DomainHandler::setURLAndID(QUrl domainURL, QUuid domainID) {
|
||||||
|
|
||||||
void DomainHandler::setIceServerHostnameAndID(const QString& iceServerHostname, const QUuid& id) {
|
void DomainHandler::setIceServerHostnameAndID(const QString& iceServerHostname, const QUuid& id) {
|
||||||
|
|
||||||
if (_iceServerSockAddr.getAddress().toString() != iceServerHostname || id != _pendingDomainID) {
|
// if it's in the error state, reset and try again.
|
||||||
|
if ((_iceServerSockAddr.getAddress().toString() != iceServerHostname || id != _pendingDomainID) || _isInErrorState) {
|
||||||
// re-set the domain info to connect to new domain
|
// re-set the domain info to connect to new domain
|
||||||
hardReset();
|
hardReset();
|
||||||
|
|
||||||
|
@ -316,6 +324,23 @@ void DomainHandler::connectedToServerless(std::map<QString, QString> namedPaths)
|
||||||
setIsConnected(true);
|
setIsConnected(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DomainHandler::loadedErrorDomain(std::map<QString, QString> namedPaths) {
|
||||||
|
auto lookup = namedPaths.find("/");
|
||||||
|
QString viewpoint;
|
||||||
|
if (lookup != namedPaths.end()) {
|
||||||
|
viewpoint = lookup->second;
|
||||||
|
} else {
|
||||||
|
viewpoint = DOMAIN_SPAWNING_POINT;
|
||||||
|
}
|
||||||
|
DependencyManager::get<AddressManager>()->goToViewpointForPath(viewpoint, QString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void DomainHandler::setRedirectErrorState(QUrl errorUrl, int reasonCode) {
|
||||||
|
_errorDomainURL = errorUrl;
|
||||||
|
_lastDomainConnectionError = reasonCode;
|
||||||
|
emit redirectToErrorDomainURL(_errorDomainURL);
|
||||||
|
}
|
||||||
|
|
||||||
void DomainHandler::requestDomainSettings() {
|
void DomainHandler::requestDomainSettings() {
|
||||||
qCDebug(networking) << "Requesting settings from domain server";
|
qCDebug(networking) << "Requesting settings from domain server";
|
||||||
|
|
||||||
|
@ -451,7 +476,18 @@ void DomainHandler::processDomainServerConnectionDeniedPacket(QSharedPointer<Rec
|
||||||
|
|
||||||
if (!_domainConnectionRefusals.contains(reasonMessage)) {
|
if (!_domainConnectionRefusals.contains(reasonMessage)) {
|
||||||
_domainConnectionRefusals.insert(reasonMessage);
|
_domainConnectionRefusals.insert(reasonMessage);
|
||||||
|
#if defined(Q_OS_ANDROID)
|
||||||
emit domainConnectionRefused(reasonMessage, (int)reasonCode, extraInfo);
|
emit domainConnectionRefused(reasonMessage, (int)reasonCode, extraInfo);
|
||||||
|
#else
|
||||||
|
if (reasonCode == ConnectionRefusedReason::ProtocolMismatch || reasonCode == ConnectionRefusedReason::NotAuthorized) {
|
||||||
|
_isInErrorState = true;
|
||||||
|
// ingest the error - this is a "hard" connection refusal.
|
||||||
|
emit redirectToErrorDomainURL(_errorDomainURL);
|
||||||
|
} else {
|
||||||
|
emit domainConnectionRefused(reasonMessage, (int)reasonCode, extraInfo);
|
||||||
|
}
|
||||||
|
_lastDomainConnectionError = (int)reasonCode;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
auto accountManager = DependencyManager::get<AccountManager>();
|
auto accountManager = DependencyManager::get<AccountManager>();
|
||||||
|
|
|
@ -50,6 +50,11 @@ public:
|
||||||
|
|
||||||
QString getHostname() const { return _domainURL.host(); }
|
QString getHostname() const { return _domainURL.host(); }
|
||||||
|
|
||||||
|
QUrl getErrorDomainURL(){ return _errorDomainURL; }
|
||||||
|
void setErrorDomainURL(const QUrl& url);
|
||||||
|
|
||||||
|
int getLastDomainConnectionError() { return _lastDomainConnectionError; }
|
||||||
|
|
||||||
const QHostAddress& getIP() const { return _sockAddr.getAddress(); }
|
const QHostAddress& getIP() const { return _sockAddr.getAddress(); }
|
||||||
void setIPToLocalhost() { _sockAddr.setAddress(QHostAddress(QHostAddress::LocalHost)); }
|
void setIPToLocalhost() { _sockAddr.setAddress(QHostAddress(QHostAddress::LocalHost)); }
|
||||||
|
|
||||||
|
@ -81,6 +86,10 @@ public:
|
||||||
|
|
||||||
void connectedToServerless(std::map<QString, QString> namedPaths);
|
void connectedToServerless(std::map<QString, QString> namedPaths);
|
||||||
|
|
||||||
|
void loadedErrorDomain(std::map<QString, QString> namedPaths);
|
||||||
|
// sets domain handler in error state.
|
||||||
|
void setRedirectErrorState(QUrl errorUrl, int reasonCode);
|
||||||
|
|
||||||
QString getViewPointFromNamedPath(QString namedPath);
|
QString getViewPointFromNamedPath(QString namedPath);
|
||||||
|
|
||||||
bool hasSettings() const { return !_settingsObject.isEmpty(); }
|
bool hasSettings() const { return !_settingsObject.isEmpty(); }
|
||||||
|
@ -135,6 +144,11 @@ public:
|
||||||
* <td><code>4</code></td>
|
* <td><code>4</code></td>
|
||||||
* <td>The domain already has its maximum number of users.</td>
|
* <td>The domain already has its maximum number of users.</td>
|
||||||
* </tr>
|
* </tr>
|
||||||
|
* <tr>
|
||||||
|
* <td><strong>TimedOut</strong></td>
|
||||||
|
* <td><code>5</code></td>
|
||||||
|
* <td>Connecting to the domain timed out.</td>
|
||||||
|
* </tr>
|
||||||
* </tbody>
|
* </tbody>
|
||||||
* </table>
|
* </table>
|
||||||
* @typedef {number} Window.ConnectionRefusedReason
|
* @typedef {number} Window.ConnectionRefusedReason
|
||||||
|
@ -144,7 +158,8 @@ public:
|
||||||
ProtocolMismatch,
|
ProtocolMismatch,
|
||||||
LoginError,
|
LoginError,
|
||||||
NotAuthorized,
|
NotAuthorized,
|
||||||
TooManyUsers
|
TooManyUsers,
|
||||||
|
TimedOut
|
||||||
};
|
};
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
@ -164,6 +179,8 @@ private slots:
|
||||||
signals:
|
signals:
|
||||||
void domainURLChanged(QUrl domainURL);
|
void domainURLChanged(QUrl domainURL);
|
||||||
|
|
||||||
|
void domainConnectionErrorChanged(int reasonCode);
|
||||||
|
|
||||||
// NOTE: the emission of completedSocketDiscovery does not mean a connection to DS is established
|
// NOTE: the emission of completedSocketDiscovery does not mean a connection to DS is established
|
||||||
// It means that, either from DNS lookup or ICE, we think we have a socket we can talk to DS on
|
// It means that, either from DNS lookup or ICE, we think we have a socket we can talk to DS on
|
||||||
void completedSocketDiscovery();
|
void completedSocketDiscovery();
|
||||||
|
@ -179,6 +196,7 @@ signals:
|
||||||
void settingsReceiveFail();
|
void settingsReceiveFail();
|
||||||
|
|
||||||
void domainConnectionRefused(QString reasonMessage, int reason, const QString& extraInfo);
|
void domainConnectionRefused(QString reasonMessage, int reason, const QString& extraInfo);
|
||||||
|
void redirectToErrorDomainURL(QUrl errorDomainURL);
|
||||||
|
|
||||||
void limitOfSilentDomainCheckInsReached();
|
void limitOfSilentDomainCheckInsReached();
|
||||||
|
|
||||||
|
@ -190,6 +208,7 @@ private:
|
||||||
QUuid _uuid;
|
QUuid _uuid;
|
||||||
Node::LocalID _localID;
|
Node::LocalID _localID;
|
||||||
QUrl _domainURL;
|
QUrl _domainURL;
|
||||||
|
QUrl _errorDomainURL;
|
||||||
HifiSockAddr _sockAddr;
|
HifiSockAddr _sockAddr;
|
||||||
QUuid _assignmentUUID;
|
QUuid _assignmentUUID;
|
||||||
QUuid _connectionToken;
|
QUuid _connectionToken;
|
||||||
|
@ -198,6 +217,7 @@ private:
|
||||||
HifiSockAddr _iceServerSockAddr;
|
HifiSockAddr _iceServerSockAddr;
|
||||||
NetworkPeer _icePeer;
|
NetworkPeer _icePeer;
|
||||||
bool _isConnected { false };
|
bool _isConnected { false };
|
||||||
|
bool _isInErrorState { false };
|
||||||
QJsonObject _settingsObject;
|
QJsonObject _settingsObject;
|
||||||
QString _pendingPath;
|
QString _pendingPath;
|
||||||
QTimer _settingsTimer;
|
QTimer _settingsTimer;
|
||||||
|
@ -210,6 +230,9 @@ private:
|
||||||
QTimer _apiRefreshTimer;
|
QTimer _apiRefreshTimer;
|
||||||
|
|
||||||
std::map<QString, QString> _namedPaths;
|
std::map<QString, QString> _namedPaths;
|
||||||
|
|
||||||
|
// domain connection error upon connection refusal.
|
||||||
|
int _lastDomainConnectionError{ -1 };
|
||||||
};
|
};
|
||||||
|
|
||||||
const QString DOMAIN_SPAWNING_POINT { "/0, -10, 0" };
|
const QString DOMAIN_SPAWNING_POINT { "/0, -10, 0" };
|
||||||
|
|
|
@ -38,10 +38,10 @@ void UserActivityLogger::logAction(QString action, QJsonObject details, JSONCall
|
||||||
if (_disabled.get()) {
|
if (_disabled.get()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto accountManager = DependencyManager::get<AccountManager>();
|
auto accountManager = DependencyManager::get<AccountManager>();
|
||||||
QHttpMultiPart* multipart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
|
QHttpMultiPart* multipart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
|
||||||
|
|
||||||
// Adding the action name
|
// Adding the action name
|
||||||
QHttpPart actionPart;
|
QHttpPart actionPart;
|
||||||
actionPart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"action_name\"");
|
actionPart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"action_name\"");
|
||||||
|
@ -53,7 +53,7 @@ void UserActivityLogger::logAction(QString action, QJsonObject details, JSONCall
|
||||||
elapsedPart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"elapsed_ms\"");
|
elapsedPart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"elapsed_ms\"");
|
||||||
elapsedPart.setBody(QString::number(_timer.elapsed()).toLocal8Bit());
|
elapsedPart.setBody(QString::number(_timer.elapsed()).toLocal8Bit());
|
||||||
multipart->append(elapsedPart);
|
multipart->append(elapsedPart);
|
||||||
|
|
||||||
// If there are action details, add them to the multipart
|
// If there are action details, add them to the multipart
|
||||||
if (!details.isEmpty()) {
|
if (!details.isEmpty()) {
|
||||||
QHttpPart detailsPart;
|
QHttpPart detailsPart;
|
||||||
|
@ -62,13 +62,13 @@ void UserActivityLogger::logAction(QString action, QJsonObject details, JSONCall
|
||||||
detailsPart.setBody(QJsonDocument(details).toJson(QJsonDocument::Compact));
|
detailsPart.setBody(QJsonDocument(details).toJson(QJsonDocument::Compact));
|
||||||
multipart->append(detailsPart);
|
multipart->append(detailsPart);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if no callbacks specified, call our owns
|
// if no callbacks specified, call our owns
|
||||||
if (params.isEmpty()) {
|
if (params.isEmpty()) {
|
||||||
params.callbackReceiver = this;
|
params.callbackReceiver = this;
|
||||||
params.errorCallbackMethod = "requestError";
|
params.errorCallbackMethod = "requestError";
|
||||||
}
|
}
|
||||||
|
|
||||||
accountManager->sendRequest(USER_ACTIVITY_URL,
|
accountManager->sendRequest(USER_ACTIVITY_URL,
|
||||||
AccountManagerAuth::Optional,
|
AccountManagerAuth::Optional,
|
||||||
QNetworkAccessManager::PostOperation,
|
QNetworkAccessManager::PostOperation,
|
||||||
|
@ -88,7 +88,7 @@ void UserActivityLogger::launch(QString applicationVersion, bool previousSession
|
||||||
actionDetails.insert(VERSION_KEY, applicationVersion);
|
actionDetails.insert(VERSION_KEY, applicationVersion);
|
||||||
actionDetails.insert(CRASH_KEY, previousSessionCrashed);
|
actionDetails.insert(CRASH_KEY, previousSessionCrashed);
|
||||||
actionDetails.insert(RUNTIME_KEY, previousSessionRuntime);
|
actionDetails.insert(RUNTIME_KEY, previousSessionRuntime);
|
||||||
|
|
||||||
logAction(ACTION_NAME, actionDetails);
|
logAction(ACTION_NAME, actionDetails);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,9 +105,9 @@ void UserActivityLogger::changedDisplayName(QString displayName) {
|
||||||
const QString ACTION_NAME = "changed_display_name";
|
const QString ACTION_NAME = "changed_display_name";
|
||||||
QJsonObject actionDetails;
|
QJsonObject actionDetails;
|
||||||
const QString DISPLAY_NAME = "display_name";
|
const QString DISPLAY_NAME = "display_name";
|
||||||
|
|
||||||
actionDetails.insert(DISPLAY_NAME, displayName);
|
actionDetails.insert(DISPLAY_NAME, displayName);
|
||||||
|
|
||||||
logAction(ACTION_NAME, actionDetails);
|
logAction(ACTION_NAME, actionDetails);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,10 +116,10 @@ void UserActivityLogger::changedModel(QString typeOfModel, QString modelURL) {
|
||||||
QJsonObject actionDetails;
|
QJsonObject actionDetails;
|
||||||
const QString TYPE_OF_MODEL = "type_of_model";
|
const QString TYPE_OF_MODEL = "type_of_model";
|
||||||
const QString MODEL_URL = "model_url";
|
const QString MODEL_URL = "model_url";
|
||||||
|
|
||||||
actionDetails.insert(TYPE_OF_MODEL, typeOfModel);
|
actionDetails.insert(TYPE_OF_MODEL, typeOfModel);
|
||||||
actionDetails.insert(MODEL_URL, modelURL);
|
actionDetails.insert(MODEL_URL, modelURL);
|
||||||
|
|
||||||
logAction(ACTION_NAME, actionDetails);
|
logAction(ACTION_NAME, actionDetails);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,9 +127,9 @@ void UserActivityLogger::changedDomain(QString domainURL) {
|
||||||
const QString ACTION_NAME = "changed_domain";
|
const QString ACTION_NAME = "changed_domain";
|
||||||
QJsonObject actionDetails;
|
QJsonObject actionDetails;
|
||||||
const QString DOMAIN_URL = "domain_url";
|
const QString DOMAIN_URL = "domain_url";
|
||||||
|
|
||||||
actionDetails.insert(DOMAIN_URL, domainURL);
|
actionDetails.insert(DOMAIN_URL, domainURL);
|
||||||
|
|
||||||
logAction(ACTION_NAME, actionDetails);
|
logAction(ACTION_NAME, actionDetails);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,10 +151,10 @@ void UserActivityLogger::connectedDevice(QString typeOfDevice, QString deviceNam
|
||||||
QJsonObject actionDetails;
|
QJsonObject actionDetails;
|
||||||
const QString TYPE_OF_DEVICE = "type_of_device";
|
const QString TYPE_OF_DEVICE = "type_of_device";
|
||||||
const QString DEVICE_NAME = "device_name";
|
const QString DEVICE_NAME = "device_name";
|
||||||
|
|
||||||
actionDetails.insert(TYPE_OF_DEVICE, typeOfDevice);
|
actionDetails.insert(TYPE_OF_DEVICE, typeOfDevice);
|
||||||
actionDetails.insert(DEVICE_NAME, deviceName);
|
actionDetails.insert(DEVICE_NAME, deviceName);
|
||||||
|
|
||||||
logAction(ACTION_NAME, actionDetails);
|
logAction(ACTION_NAME, actionDetails);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -163,9 +163,9 @@ void UserActivityLogger::loadedScript(QString scriptName) {
|
||||||
const QString ACTION_NAME = "loaded_script";
|
const QString ACTION_NAME = "loaded_script";
|
||||||
QJsonObject actionDetails;
|
QJsonObject actionDetails;
|
||||||
const QString SCRIPT_NAME = "script_name";
|
const QString SCRIPT_NAME = "script_name";
|
||||||
|
|
||||||
actionDetails.insert(SCRIPT_NAME, scriptName);
|
actionDetails.insert(SCRIPT_NAME, scriptName);
|
||||||
|
|
||||||
logAction(ACTION_NAME, actionDetails);
|
logAction(ACTION_NAME, actionDetails);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -199,10 +199,10 @@ void UserActivityLogger::wentTo(AddressManager::LookupTrigger lookupTrigger, QSt
|
||||||
const QString TRIGGER_TYPE_KEY = "trigger";
|
const QString TRIGGER_TYPE_KEY = "trigger";
|
||||||
const QString DESTINATION_TYPE_KEY = "destination_type";
|
const QString DESTINATION_TYPE_KEY = "destination_type";
|
||||||
const QString DESTINATION_NAME_KEY = "detination_name";
|
const QString DESTINATION_NAME_KEY = "detination_name";
|
||||||
|
|
||||||
actionDetails.insert(TRIGGER_TYPE_KEY, trigger);
|
actionDetails.insert(TRIGGER_TYPE_KEY, trigger);
|
||||||
actionDetails.insert(DESTINATION_TYPE_KEY, destinationType);
|
actionDetails.insert(DESTINATION_TYPE_KEY, destinationType);
|
||||||
actionDetails.insert(DESTINATION_NAME_KEY, destinationName);
|
actionDetails.insert(DESTINATION_NAME_KEY, destinationName);
|
||||||
|
|
||||||
logAction(ACTION_NAME, actionDetails);
|
logAction(ACTION_NAME, actionDetails);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ var DEFAULT_SCRIPTS_COMBINED = [
|
||||||
];
|
];
|
||||||
var DEFAULT_SCRIPTS_SEPARATE = [
|
var DEFAULT_SCRIPTS_SEPARATE = [
|
||||||
"system/controllers/controllerScripts.js",
|
"system/controllers/controllerScripts.js",
|
||||||
|
"system/interstitialPage.js"
|
||||||
//"system/chat.js"
|
//"system/chat.js"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
476
scripts/system/interstitialPage.js
Normal file
|
@ -0,0 +1,476 @@
|
||||||
|
//
|
||||||
|
// interstitialPage.js
|
||||||
|
// scripts/system
|
||||||
|
//
|
||||||
|
// Created by Dante Ruiz on 08/02/2018.
|
||||||
|
// Copyright 2012 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
|
||||||
|
//
|
||||||
|
|
||||||
|
/* global Script, Controller, Overlays, Quat, MyAvatar, Entities, print, Vec3, AddressManager, Render, Window, Toolbars,
|
||||||
|
Camera, HMD, location, Account, Xform*/
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
Script.include("/~/system/libraries/Xform.js");
|
||||||
|
var DEBUG = false;
|
||||||
|
var MIN_LOADING_PROGRESS = 3.6;
|
||||||
|
var TOTAL_LOADING_PROGRESS = 3.8;
|
||||||
|
var EPSILON = 0.01;
|
||||||
|
var isVisible = false;
|
||||||
|
var VOLUME = 0.4;
|
||||||
|
var tune = SoundCache.getSound("http://hifi-content.s3.amazonaws.com/alexia/LoadingScreens/crystals_and_voices.wav");
|
||||||
|
var sample = null;
|
||||||
|
var MAX_LEFT_MARGIN = 1.9;
|
||||||
|
var INNER_CIRCLE_WIDTH = 4.7;
|
||||||
|
var DEFAULT_Z_OFFSET = 5.45;
|
||||||
|
var previousCameraMode = Camera.mode;
|
||||||
|
|
||||||
|
var renderViewTask = Render.getConfig("RenderMainView");
|
||||||
|
var toolbar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system");
|
||||||
|
var request = Script.require('request').request;
|
||||||
|
var BUTTON_PROPERTIES = {
|
||||||
|
text: "Interstitial"
|
||||||
|
};
|
||||||
|
|
||||||
|
var tablet = null;
|
||||||
|
var button = null;
|
||||||
|
|
||||||
|
// Tips have a character limit of 69
|
||||||
|
var userTips = [
|
||||||
|
"Tip: Visit TheSpot to explore featured domains!",
|
||||||
|
"Tip: Visit our docs online to learn more about scripting!",
|
||||||
|
"Tip: Don't want others invading your personal space? Turn on the Bubble!",
|
||||||
|
"Tip: Want to make a friend? Shake hands with them in VR!",
|
||||||
|
"Tip: Enjoy live music? Visit Rust to dance your heart out!",
|
||||||
|
"Tip: Have you visited BodyMart to check out the new avatars recently?",
|
||||||
|
"Tip: Use the Create app to import models and create custom entities.",
|
||||||
|
"Tip: We're open source! Feel free to contribute to our code on GitHub!",
|
||||||
|
"Tip: What emotes have you used in the Emote app?",
|
||||||
|
"Tip: Take and share your snapshots with the everyone using the Snap app.",
|
||||||
|
"Tip: Did you know you can show websites in-world by creating a web entity?",
|
||||||
|
"Tip: Find out more information about domains by visiting our website!",
|
||||||
|
"Tip: Did you know you can get cool new apps from the Marketplace?",
|
||||||
|
"Tip: Print your snapshots from the Snap app to share with others!",
|
||||||
|
"Tip: Log in to make friends, visit new domains, and save avatars!"
|
||||||
|
];
|
||||||
|
|
||||||
|
var DEFAULT_DIMENSIONS = { x: 24, y: 24, z: 24 };
|
||||||
|
|
||||||
|
var loadingSphereID = Overlays.addOverlay("model", {
|
||||||
|
name: "Loading-Sphere",
|
||||||
|
position: Vec3.sum(Vec3.sum(MyAvatar.position, {x: 0.0, y: -1.0, z: 0.0}), Vec3.multiplyQbyV(MyAvatar.orientation, {x: 0, y: 0.95, z: 0})),
|
||||||
|
orientation: Quat.multiply(Quat.fromVec3Degrees({x: 0, y: 180, z: 0}), MyAvatar.orientation),
|
||||||
|
url: "http://hifi-content.s3.amazonaws.com/alexia/LoadingScreens/black-sphere.fbx",
|
||||||
|
dimensions: DEFAULT_DIMENSIONS,
|
||||||
|
alpha: 1,
|
||||||
|
visible: isVisible,
|
||||||
|
ignoreRayIntersection: true,
|
||||||
|
drawInFront: true,
|
||||||
|
grabbable: false,
|
||||||
|
parentID: MyAvatar.SELF_ID
|
||||||
|
});
|
||||||
|
|
||||||
|
var anchorOverlay = Overlays.addOverlay("cube", {
|
||||||
|
dimensions: {x: 0.2, y: 0.2, z: 0.2},
|
||||||
|
visible: false,
|
||||||
|
grabbable: false,
|
||||||
|
ignoreRayIntersection: true,
|
||||||
|
localPosition: {x: 0.0, y: getAnchorLocalYOffset(), z: DEFAULT_Z_OFFSET },
|
||||||
|
orientation: Quat.multiply(Quat.fromVec3Degrees({x: 0, y: 180, z: 0}), MyAvatar.orientation),
|
||||||
|
solid: true,
|
||||||
|
drawInFront: true,
|
||||||
|
parentID: loadingSphereID
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var domainName = "";
|
||||||
|
var domainNameTextID = Overlays.addOverlay("text3d", {
|
||||||
|
name: "Loading-Destination-Card-Text",
|
||||||
|
localPosition: { x: 0.0, y: 0.8, z: -0.001 },
|
||||||
|
text: domainName,
|
||||||
|
textAlpha: 1,
|
||||||
|
backgroundAlpha: 1,
|
||||||
|
lineHeight: 0.42,
|
||||||
|
visible: isVisible,
|
||||||
|
ignoreRayIntersection: true,
|
||||||
|
drawInFront: true,
|
||||||
|
grabbable: false,
|
||||||
|
localOrientation: Quat.fromVec3Degrees({ x: 0, y: 180, z: 0 }),
|
||||||
|
parentID: anchorOverlay
|
||||||
|
});
|
||||||
|
|
||||||
|
var domainText = "";
|
||||||
|
var domainDescription = Overlays.addOverlay("text3d", {
|
||||||
|
name: "Loading-Hostname",
|
||||||
|
localPosition: { x: 0.0, y: 0.32, z: 0.0 },
|
||||||
|
text: domainText,
|
||||||
|
textAlpha: 1,
|
||||||
|
backgroundAlpha: 1,
|
||||||
|
lineHeight: 0.13,
|
||||||
|
visible: isVisible,
|
||||||
|
backgroundAlpha: 0,
|
||||||
|
ignoreRayIntersection: true,
|
||||||
|
drawInFront: true,
|
||||||
|
grabbable: false,
|
||||||
|
localOrientation: Quat.fromVec3Degrees({ x: 0, y: 180, z: 0 }),
|
||||||
|
parentID: anchorOverlay
|
||||||
|
});
|
||||||
|
|
||||||
|
var toolTip = "";
|
||||||
|
|
||||||
|
var domainToolTip = Overlays.addOverlay("text3d", {
|
||||||
|
name: "Loading-Tooltip",
|
||||||
|
localPosition: { x: 0.0 , y: -1.6, z: 0.0 },
|
||||||
|
text: toolTip,
|
||||||
|
textAlpha: 1,
|
||||||
|
backgroundAlpha: 1,
|
||||||
|
lineHeight: 0.13,
|
||||||
|
visible: isVisible,
|
||||||
|
ignoreRayIntersection: true,
|
||||||
|
drawInFront: true,
|
||||||
|
grabbable: false,
|
||||||
|
localOrientation: Quat.fromVec3Degrees({ x: 0, y: 180, z: 0 }),
|
||||||
|
parentID: anchorOverlay
|
||||||
|
});
|
||||||
|
|
||||||
|
var loadingToTheSpotID = Overlays.addOverlay("image3d", {
|
||||||
|
name: "Loading-Destination-Card-Text",
|
||||||
|
localPosition: { x: 0.0 , y: -1.8, z: 0.0 },
|
||||||
|
url: "http://hifi-content.s3.amazonaws.com/alexia/LoadingScreens/goTo_button.png",
|
||||||
|
alpha: 1,
|
||||||
|
dimensions: { x: 1.2, y: 0.6},
|
||||||
|
visible: isVisible,
|
||||||
|
emissive: true,
|
||||||
|
ignoreRayIntersection: false,
|
||||||
|
drawInFront: true,
|
||||||
|
grabbable: false,
|
||||||
|
localOrientation: Quat.fromVec3Degrees({ x: 0.0, y: 180.0, z: 0.0 }),
|
||||||
|
parentID: anchorOverlay
|
||||||
|
});
|
||||||
|
|
||||||
|
var loadingBarPlacard = Overlays.addOverlay("image3d", {
|
||||||
|
name: "Loading-Bar-Placard",
|
||||||
|
localPosition: { x: 0.0, y: -0.99, z: 0.3 },
|
||||||
|
url: Script.resourcesPath() + "images/loadingBar_placard.png",
|
||||||
|
alpha: 1,
|
||||||
|
dimensions: { x: 4, y: 2.8},
|
||||||
|
visible: isVisible,
|
||||||
|
emissive: true,
|
||||||
|
ignoreRayIntersection: false,
|
||||||
|
drawInFront: true,
|
||||||
|
grabbable: false,
|
||||||
|
localOrientation: Quat.fromVec3Degrees({ x: 0.0, y: 180.0, z: 0.0 }),
|
||||||
|
parentID: anchorOverlay
|
||||||
|
});
|
||||||
|
|
||||||
|
var loadingBarProgress = Overlays.addOverlay("image3d", {
|
||||||
|
name: "Loading-Bar-Progress",
|
||||||
|
localPosition: { x: 0.0, y: -0.90, z: 0.0 },
|
||||||
|
url: Script.resourcesPath() + "images/loadingBar_progress.png",
|
||||||
|
alpha: 1,
|
||||||
|
dimensions: {x: 3.8, y: 2.8},
|
||||||
|
visible: isVisible,
|
||||||
|
emissive: true,
|
||||||
|
ignoreRayIntersection: false,
|
||||||
|
drawInFront: true,
|
||||||
|
grabbable: false,
|
||||||
|
localOrientation: Quat.fromVec3Degrees({ x: 0.0, y: 180.0, z: 0.0 }),
|
||||||
|
parentID: anchorOverlay
|
||||||
|
});
|
||||||
|
|
||||||
|
var TARGET_UPDATE_HZ = 60; // 50hz good enough, but we're using update
|
||||||
|
var BASIC_TIMER_INTERVAL_MS = 1000 / TARGET_UPDATE_HZ;
|
||||||
|
var lastInterval = Date.now();
|
||||||
|
var currentDomain = "no domain";
|
||||||
|
var timer = null;
|
||||||
|
var target = 0;
|
||||||
|
|
||||||
|
var connectionToDomainFailed = false;
|
||||||
|
|
||||||
|
|
||||||
|
function getAnchorLocalYOffset() {
|
||||||
|
var loadingSpherePosition = Overlays.getProperty(loadingSphereID, "position");
|
||||||
|
var loadingSphereOrientation = Overlays.getProperty(loadingSphereID, "rotation");
|
||||||
|
var overlayXform = new Xform(loadingSphereOrientation, loadingSpherePosition);
|
||||||
|
var worldToOverlayXform = overlayXform.inv();
|
||||||
|
var headPosition = MyAvatar.getHeadPosition();
|
||||||
|
var headPositionInOverlaySpace = worldToOverlayXform.xformPoint(headPosition);
|
||||||
|
return headPositionInOverlaySpace.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLeftMargin(overlayID, text) {
|
||||||
|
var textSize = Overlays.textSize(overlayID, text);
|
||||||
|
var sizeDifference = ((INNER_CIRCLE_WIDTH - textSize.width) / 2);
|
||||||
|
var leftMargin = -(MAX_LEFT_MARGIN - sizeDifference);
|
||||||
|
return leftMargin;
|
||||||
|
}
|
||||||
|
|
||||||
|
function lerp(a, b, t) {
|
||||||
|
return ((1 - t) * a + t * b);
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetValues() {
|
||||||
|
var properties = {
|
||||||
|
localPosition: { x: 1.85, y: -0.935, z: 0.0 },
|
||||||
|
dimensions: {
|
||||||
|
x: 0.1,
|
||||||
|
y: 2.8
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Overlays.editOverlay(loadingBarProgress, properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
function startInterstitialPage() {
|
||||||
|
if (timer === null) {
|
||||||
|
updateOverlays(false);
|
||||||
|
startAudio();
|
||||||
|
target = 0;
|
||||||
|
currentProgress = 0.1;
|
||||||
|
connectionToDomainFailed = false;
|
||||||
|
previousCameraMode = Camera.mode;
|
||||||
|
Camera.mode = "first person";
|
||||||
|
timer = Script.setTimeout(update, BASIC_TIMER_INTERVAL_MS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function startAudio() {
|
||||||
|
sample = Audio.playSound(tune, {
|
||||||
|
localOnly: true,
|
||||||
|
position: MyAvatar.getHeadPosition(),
|
||||||
|
volume: VOLUME
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function endAudio() {
|
||||||
|
sample.stop();
|
||||||
|
sample = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function domainChanged(domain) {
|
||||||
|
if (domain !== currentDomain) {
|
||||||
|
MyAvatar.restoreAnimation();
|
||||||
|
var name = location.placename;
|
||||||
|
domainName = name.charAt(0).toUpperCase() + name.slice(1);
|
||||||
|
var doRequest = true;
|
||||||
|
if (name.length === 0 && location.href === "file:///~/serverless/tutorial.json") {
|
||||||
|
domainName = "Serveless Domain (Tutorial)";
|
||||||
|
doRequest = false;
|
||||||
|
}
|
||||||
|
var domainNameLeftMargin = getLeftMargin(domainNameTextID, domainName);
|
||||||
|
var textProperties = {
|
||||||
|
text: domainName,
|
||||||
|
leftMargin: domainNameLeftMargin
|
||||||
|
};
|
||||||
|
|
||||||
|
if (doRequest) {
|
||||||
|
var url = Account.metaverseServerURL + '/api/v1/places/' + domain;
|
||||||
|
request({
|
||||||
|
uri: url
|
||||||
|
}, function(error, data) {
|
||||||
|
if (data.status === "success") {
|
||||||
|
var domainInfo = data.data;
|
||||||
|
var domainDescriptionText = domainInfo.place.description;
|
||||||
|
var leftMargin = getLeftMargin(domainDescription, domainDescriptionText);
|
||||||
|
var domainDescriptionProperties = {
|
||||||
|
text: domainDescriptionText,
|
||||||
|
leftMargin: leftMargin
|
||||||
|
};
|
||||||
|
Overlays.editOverlay(domainDescription, domainDescriptionProperties);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
var domainDescriptionProperties = {
|
||||||
|
text: ""
|
||||||
|
};
|
||||||
|
Overlays.editOverlay(domainDescription, domainDescriptionProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
var randomIndex = Math.floor(Math.random() * userTips.length);
|
||||||
|
var tip = userTips[randomIndex];
|
||||||
|
var tipLeftMargin = getLeftMargin(domainToolTip, tip);
|
||||||
|
var toolTipProperties = {
|
||||||
|
text: tip,
|
||||||
|
leftMargin: tipLeftMargin
|
||||||
|
};
|
||||||
|
|
||||||
|
Overlays.editOverlay(domainNameTextID, textProperties);
|
||||||
|
Overlays.editOverlay(domainToolTip, toolTipProperties);
|
||||||
|
|
||||||
|
|
||||||
|
startInterstitialPage();
|
||||||
|
currentDomain = domain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var THE_PLACE = (HifiAbout.buildVersion === "dev") ? "hifi://TheSpot-dev": "hifi://TheSpot";
|
||||||
|
function clickedOnOverlay(overlayID, event) {
|
||||||
|
if (loadingToTheSpotID === overlayID) {
|
||||||
|
location.handleLookupString(THE_PLACE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentProgress = 0.1;
|
||||||
|
|
||||||
|
function updateOverlays(physicsEnabled) {
|
||||||
|
var properties = {
|
||||||
|
visible: !physicsEnabled
|
||||||
|
};
|
||||||
|
|
||||||
|
var mainSphereProperties = {
|
||||||
|
visible: !physicsEnabled
|
||||||
|
};
|
||||||
|
|
||||||
|
var domainTextProperties = {
|
||||||
|
text: domainText,
|
||||||
|
visible: !physicsEnabled
|
||||||
|
};
|
||||||
|
|
||||||
|
var loadingBarProperties = {
|
||||||
|
dimensions: { x: 0.0, y: 2.8 },
|
||||||
|
visible: !physicsEnabled
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!HMD.active) {
|
||||||
|
MyAvatar.headOrientation = Quat.multiply(Quat.cancelOutRollAndPitch(MyAvatar.headOrientation), Quat.fromPitchYawRollDegrees(-3.0, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
renderViewTask.getConfig("LightingModel")["enableAmbientLight"] = physicsEnabled;
|
||||||
|
renderViewTask.getConfig("LightingModel")["enableDirectionalLight"] = physicsEnabled;
|
||||||
|
renderViewTask.getConfig("LightingModel")["enablePointLight"] = physicsEnabled;
|
||||||
|
Overlays.editOverlay(loadingSphereID, mainSphereProperties);
|
||||||
|
Overlays.editOverlay(loadingToTheSpotID, properties);
|
||||||
|
Overlays.editOverlay(domainNameTextID, properties);
|
||||||
|
Overlays.editOverlay(domainDescription, domainTextProperties);
|
||||||
|
Overlays.editOverlay(domainToolTip, properties);
|
||||||
|
Overlays.editOverlay(loadingBarPlacard, properties);
|
||||||
|
Overlays.editOverlay(loadingBarProgress, loadingBarProperties);
|
||||||
|
|
||||||
|
|
||||||
|
Menu.setIsOptionChecked("Show Overlays", physicsEnabled);
|
||||||
|
if (!HMD.active) {
|
||||||
|
toolbar.writeProperty("visible", physicsEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
resetValues();
|
||||||
|
|
||||||
|
if (physicsEnabled) {
|
||||||
|
Camera.mode = previousCameraMode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function scaleInterstitialPage(sensorToWorldScale) {
|
||||||
|
var yOffset = getAnchorLocalYOffset();
|
||||||
|
var localPosition = {
|
||||||
|
x: 0.0,
|
||||||
|
y: yOffset,
|
||||||
|
z: 5.45
|
||||||
|
};
|
||||||
|
|
||||||
|
Overlays.editOverlay(anchorOverlay, { localPosition: localPosition });
|
||||||
|
}
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
var physicsEnabled = Window.isPhysicsEnabled();
|
||||||
|
var thisInterval = Date.now();
|
||||||
|
var deltaTime = (thisInterval - lastInterval);
|
||||||
|
lastInterval = thisInterval;
|
||||||
|
|
||||||
|
var domainLoadingProgressPercentage = Window.domainLoadingProgress();
|
||||||
|
|
||||||
|
var progress = MIN_LOADING_PROGRESS * domainLoadingProgressPercentage;
|
||||||
|
if (progress >= target) {
|
||||||
|
target = progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((physicsEnabled && (currentProgress < TOTAL_LOADING_PROGRESS))) {
|
||||||
|
target = TOTAL_LOADING_PROGRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentProgress = lerp(currentProgress, target, 0.2);
|
||||||
|
var properties = {
|
||||||
|
localPosition: { x: (1.85 - (currentProgress / 2) - (-0.029 * (currentProgress / TOTAL_LOADING_PROGRESS))), y: -0.935, z: 0.0 },
|
||||||
|
dimensions: {
|
||||||
|
x: currentProgress,
|
||||||
|
y: 2.8
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Overlays.editOverlay(loadingBarProgress, properties);
|
||||||
|
if ((physicsEnabled && (currentProgress >= (TOTAL_LOADING_PROGRESS - EPSILON)))) {
|
||||||
|
updateOverlays((physicsEnabled || connectionToDomainFailed));
|
||||||
|
endAudio();
|
||||||
|
currentDomain = "no domain";
|
||||||
|
timer = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
timer = Script.setTimeout(update, BASIC_TIMER_INTERVAL_MS);
|
||||||
|
}
|
||||||
|
var whiteColor = {red: 255, green: 255, blue: 255};
|
||||||
|
var greyColor = {red: 125, green: 125, blue: 125};
|
||||||
|
Overlays.mouseReleaseOnOverlay.connect(clickedOnOverlay);
|
||||||
|
Overlays.hoverEnterOverlay.connect(function(overlayID, event) {
|
||||||
|
if (overlayID === loadingToTheSpotID) {
|
||||||
|
Overlays.editOverlay(loadingToTheSpotID, { color: greyColor});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Overlays.hoverLeaveOverlay.connect(function(overlayID, event) {
|
||||||
|
if (overlayID === loadingToTheSpotID) {
|
||||||
|
Overlays.editOverlay(loadingToTheSpotID, { color: whiteColor});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
location.hostChanged.connect(domainChanged);
|
||||||
|
location.lookupResultsFinished.connect(function() {
|
||||||
|
Script.setTimeout(function() {
|
||||||
|
connectionToDomainFailed = !location.isConnected;
|
||||||
|
}, 1200);
|
||||||
|
});
|
||||||
|
|
||||||
|
MyAvatar.sensorToWorldScaleChanged.connect(scaleInterstitialPage);
|
||||||
|
MyAvatar.sessionUUIDChanged.connect(function() {
|
||||||
|
var avatarSessionUUID = MyAvatar.sessionUUID;
|
||||||
|
Overlays.editOverlay(loadingSphereID, { parentID: avatarSessionUUID });
|
||||||
|
});
|
||||||
|
|
||||||
|
var toggle = true;
|
||||||
|
if (DEBUG) {
|
||||||
|
tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||||
|
button = tablet.addButton(BUTTON_PROPERTIES);
|
||||||
|
|
||||||
|
button.clicked.connect(function() {
|
||||||
|
toggle = !toggle;
|
||||||
|
updateOverlays(toggle);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function cleanup() {
|
||||||
|
Overlays.deleteOverlay(loadingSphereID);
|
||||||
|
Overlays.deleteOverlay(loadingToTheSpotID);
|
||||||
|
Overlays.deleteOverlay(domainNameTextID);
|
||||||
|
Overlays.deleteOverlay(domainDescription);
|
||||||
|
Overlays.deleteOverlay(domainToolTip);
|
||||||
|
Overlays.deleteOverlay(loadingBarPlacard);
|
||||||
|
Overlays.deleteOverlay(loadingBarProgress);
|
||||||
|
Overlays.deleteOverlay(anchorOverlay);
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
tablet.removeButton(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderViewTask.getConfig("LightingModel")["enableAmbientLight"] = true;
|
||||||
|
renderViewTask.getConfig("LightingModel")["enableDirectionalLight"] = true;
|
||||||
|
renderViewTask.getConfig("LightingModel")["enablePointLight"] = true;
|
||||||
|
Menu.setIsOptionChecked("Show Overlays", true);
|
||||||
|
if (!HMD.active) {
|
||||||
|
toolbar.writeProperty("visible", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Script.scriptEnding.connect(cleanup);
|
||||||
|
}());
|
|
@ -410,7 +410,7 @@ SelectionDisplay = (function() {
|
||||||
var COLOR_RED = { red: 226, green: 51, blue: 77 };
|
var COLOR_RED = { red: 226, green: 51, blue: 77 };
|
||||||
var COLOR_HOVER = { red: 227, green: 227, blue: 227 };
|
var COLOR_HOVER = { red: 227, green: 227, blue: 227 };
|
||||||
var COLOR_ROTATE_CURRENT_RING = { red: 255, green: 99, blue: 9 };
|
var COLOR_ROTATE_CURRENT_RING = { red: 255, green: 99, blue: 9 };
|
||||||
var COLOR_SCALE_EDGE = { red: 87, green: 87, blue: 87 };
|
var COLOR_BOUNDING_EDGE = { red: 87, green: 87, blue: 87 };
|
||||||
var COLOR_SCALE_CUBE = { red: 106, green: 106, blue: 106 };
|
var COLOR_SCALE_CUBE = { red: 106, green: 106, blue: 106 };
|
||||||
var COLOR_SCALE_CUBE_SELECTED = { red: 18, green: 18, blue: 18 };
|
var COLOR_SCALE_CUBE_SELECTED = { red: 18, green: 18, blue: 18 };
|
||||||
|
|
||||||
|
@ -433,15 +433,15 @@ SelectionDisplay = (function() {
|
||||||
var ROTATE_DISPLAY_SIZE_Y_MULTIPLIER = 0.09;
|
var ROTATE_DISPLAY_SIZE_Y_MULTIPLIER = 0.09;
|
||||||
var ROTATE_DISPLAY_LINE_HEIGHT_MULTIPLIER = 0.07;
|
var ROTATE_DISPLAY_LINE_HEIGHT_MULTIPLIER = 0.07;
|
||||||
|
|
||||||
var STRETCH_SPHERE_OFFSET = 0.06;
|
var STRETCH_CUBE_OFFSET = 0.06;
|
||||||
var STRETCH_SPHERE_CAMERA_DISTANCE_MULTIPLE = 0.01;
|
var STRETCH_CUBE_CAMERA_DISTANCE_MULTIPLE = 0.02;
|
||||||
var STRETCH_MINIMUM_DIMENSION = 0.001;
|
var STRETCH_MINIMUM_DIMENSION = 0.001;
|
||||||
var STRETCH_ALL_MINIMUM_DIMENSION = 0.01;
|
var STRETCH_ALL_MINIMUM_DIMENSION = 0.01;
|
||||||
var STRETCH_DIRECTION_ALL_CAMERA_DISTANCE_MULTIPLE = 6;
|
var STRETCH_DIRECTION_ALL_CAMERA_DISTANCE_MULTIPLE = 2;
|
||||||
var STRETCH_PANEL_WIDTH = 0.01;
|
var STRETCH_PANEL_WIDTH = 0.01;
|
||||||
|
|
||||||
var SCALE_CUBE_OFFSET = 0.5;
|
var BOUNDING_EDGE_OFFSET = 0.5;
|
||||||
var SCALE_CUBE_CAMERA_DISTANCE_MULTIPLE = 0.0125;
|
var SCALE_CUBE_CAMERA_DISTANCE_MULTIPLE = 0.02;
|
||||||
|
|
||||||
var CLONER_OFFSET = { x: 0.9, y: -0.9, z: 0.9 };
|
var CLONER_OFFSET = { x: 0.9, y: -0.9, z: 0.9 };
|
||||||
|
|
||||||
|
@ -495,6 +495,8 @@ SelectionDisplay = (function() {
|
||||||
var worldRotationX;
|
var worldRotationX;
|
||||||
var worldRotationY;
|
var worldRotationY;
|
||||||
var worldRotationZ;
|
var worldRotationZ;
|
||||||
|
|
||||||
|
var activeStretchCubePanelOffset = null;
|
||||||
|
|
||||||
var previousHandle = null;
|
var previousHandle = null;
|
||||||
var previousHandleHelper = null;
|
var previousHandleHelper = null;
|
||||||
|
@ -589,20 +591,18 @@ SelectionDisplay = (function() {
|
||||||
leftMargin: 0
|
leftMargin: 0
|
||||||
});
|
});
|
||||||
|
|
||||||
var handlePropertiesStretchSpheres = {
|
var handlePropertiesStretchCubes = {
|
||||||
alpha: 1,
|
|
||||||
shape: "Sphere",
|
|
||||||
solid: true,
|
solid: true,
|
||||||
visible: false,
|
visible: false,
|
||||||
ignoreRayIntersection: false,
|
ignoreRayIntersection: false,
|
||||||
drawInFront: true
|
drawInFront: true
|
||||||
};
|
};
|
||||||
var handleStretchXSphere = Overlays.addOverlay("shape", handlePropertiesStretchSpheres);
|
var handleStretchXCube = Overlays.addOverlay("cube", handlePropertiesStretchCubes);
|
||||||
Overlays.editOverlay(handleStretchXSphere, { color: COLOR_RED });
|
Overlays.editOverlay(handleStretchXCube, { color: COLOR_RED });
|
||||||
var handleStretchYSphere = Overlays.addOverlay("shape", handlePropertiesStretchSpheres);
|
var handleStretchYCube = Overlays.addOverlay("cube", handlePropertiesStretchCubes);
|
||||||
Overlays.editOverlay(handleStretchYSphere, { color: COLOR_GREEN });
|
Overlays.editOverlay(handleStretchYCube, { color: COLOR_GREEN });
|
||||||
var handleStretchZSphere = Overlays.addOverlay("shape", handlePropertiesStretchSpheres);
|
var handleStretchZCube = Overlays.addOverlay("cube", handlePropertiesStretchCubes);
|
||||||
Overlays.editOverlay(handleStretchZSphere, { color: COLOR_BLUE });
|
Overlays.editOverlay(handleStretchZCube, { color: COLOR_BLUE });
|
||||||
|
|
||||||
var handlePropertiesStretchPanel = {
|
var handlePropertiesStretchPanel = {
|
||||||
shape: "Quad",
|
shape: "Quad",
|
||||||
|
@ -619,8 +619,7 @@ SelectionDisplay = (function() {
|
||||||
var handleStretchZPanel = Overlays.addOverlay("shape", handlePropertiesStretchPanel);
|
var handleStretchZPanel = Overlays.addOverlay("shape", handlePropertiesStretchPanel);
|
||||||
Overlays.editOverlay(handleStretchZPanel, { color: COLOR_BLUE });
|
Overlays.editOverlay(handleStretchZPanel, { color: COLOR_BLUE });
|
||||||
|
|
||||||
var handlePropertiesScaleCubes = {
|
var handleScaleCube = Overlays.addOverlay("cube", {
|
||||||
alpha: 1,
|
|
||||||
size: 0.025,
|
size: 0.025,
|
||||||
color: COLOR_SCALE_CUBE,
|
color: COLOR_SCALE_CUBE,
|
||||||
solid: true,
|
solid: true,
|
||||||
|
@ -628,36 +627,28 @@ SelectionDisplay = (function() {
|
||||||
ignoreRayIntersection: false,
|
ignoreRayIntersection: false,
|
||||||
drawInFront: true,
|
drawInFront: true,
|
||||||
borderSize: 1.4
|
borderSize: 1.4
|
||||||
};
|
});
|
||||||
var handleScaleLBNCube = Overlays.addOverlay("cube", handlePropertiesScaleCubes); // (-x, -y, -z)
|
|
||||||
var handleScaleRBNCube = Overlays.addOverlay("cube", handlePropertiesScaleCubes); // ( x, -y, -z)
|
|
||||||
var handleScaleLBFCube = Overlays.addOverlay("cube", handlePropertiesScaleCubes); // (-x, -y, z)
|
|
||||||
var handleScaleRBFCube = Overlays.addOverlay("cube", handlePropertiesScaleCubes); // ( x, -y, z)
|
|
||||||
var handleScaleLTNCube = Overlays.addOverlay("cube", handlePropertiesScaleCubes); // (-x, y, -z)
|
|
||||||
var handleScaleRTNCube = Overlays.addOverlay("cube", handlePropertiesScaleCubes); // ( x, y, -z)
|
|
||||||
var handleScaleLTFCube = Overlays.addOverlay("cube", handlePropertiesScaleCubes); // (-x, y, z)
|
|
||||||
var handleScaleRTFCube = Overlays.addOverlay("cube", handlePropertiesScaleCubes); // ( x, y, z)
|
|
||||||
|
|
||||||
var handlePropertiesScaleEdge = {
|
var handlePropertiesBoundingEdge = {
|
||||||
alpha: 1,
|
alpha: 1,
|
||||||
color: COLOR_SCALE_EDGE,
|
color: COLOR_BOUNDING_EDGE,
|
||||||
visible: false,
|
visible: false,
|
||||||
ignoreRayIntersection: true,
|
ignoreRayIntersection: true,
|
||||||
drawInFront: true,
|
drawInFront: true,
|
||||||
lineWidth: 0.2
|
lineWidth: 0.2
|
||||||
};
|
};
|
||||||
var handleScaleTREdge = Overlays.addOverlay("line3d", handlePropertiesScaleEdge);
|
var handleBoundingTREdge = Overlays.addOverlay("line3d", handlePropertiesBoundingEdge);
|
||||||
var handleScaleTLEdge = Overlays.addOverlay("line3d", handlePropertiesScaleEdge);
|
var handleBoundingTLEdge = Overlays.addOverlay("line3d", handlePropertiesBoundingEdge);
|
||||||
var handleScaleTFEdge = Overlays.addOverlay("line3d", handlePropertiesScaleEdge);
|
var handleBoundingTFEdge = Overlays.addOverlay("line3d", handlePropertiesBoundingEdge);
|
||||||
var handleScaleTNEdge = Overlays.addOverlay("line3d", handlePropertiesScaleEdge);
|
var handleBoundingTNEdge = Overlays.addOverlay("line3d", handlePropertiesBoundingEdge);
|
||||||
var handleScaleBREdge = Overlays.addOverlay("line3d", handlePropertiesScaleEdge);
|
var handleBoundingBREdge = Overlays.addOverlay("line3d", handlePropertiesBoundingEdge);
|
||||||
var handleScaleBLEdge = Overlays.addOverlay("line3d", handlePropertiesScaleEdge);
|
var handleBoundingBLEdge = Overlays.addOverlay("line3d", handlePropertiesBoundingEdge);
|
||||||
var handleScaleBFEdge = Overlays.addOverlay("line3d", handlePropertiesScaleEdge);
|
var handleBoundingBFEdge = Overlays.addOverlay("line3d", handlePropertiesBoundingEdge);
|
||||||
var handleScaleBNEdge = Overlays.addOverlay("line3d", handlePropertiesScaleEdge);
|
var handleBoundingBNEdge = Overlays.addOverlay("line3d", handlePropertiesBoundingEdge);
|
||||||
var handleScaleNREdge = Overlays.addOverlay("line3d", handlePropertiesScaleEdge);
|
var handleBoundingNREdge = Overlays.addOverlay("line3d", handlePropertiesBoundingEdge);
|
||||||
var handleScaleNLEdge = Overlays.addOverlay("line3d", handlePropertiesScaleEdge);
|
var handleBoundingNLEdge = Overlays.addOverlay("line3d", handlePropertiesBoundingEdge);
|
||||||
var handleScaleFREdge = Overlays.addOverlay("line3d", handlePropertiesScaleEdge);
|
var handleBoundingFREdge = Overlays.addOverlay("line3d", handlePropertiesBoundingEdge);
|
||||||
var handleScaleFLEdge = Overlays.addOverlay("line3d", handlePropertiesScaleEdge);
|
var handleBoundingFLEdge = Overlays.addOverlay("line3d", handlePropertiesBoundingEdge);
|
||||||
|
|
||||||
var handleCloner = Overlays.addOverlay("cube", {
|
var handleCloner = Overlays.addOverlay("cube", {
|
||||||
alpha: 1,
|
alpha: 1,
|
||||||
|
@ -738,32 +729,25 @@ SelectionDisplay = (function() {
|
||||||
handleRotateRollRing,
|
handleRotateRollRing,
|
||||||
handleRotateCurrentRing,
|
handleRotateCurrentRing,
|
||||||
rotationDegreesDisplay,
|
rotationDegreesDisplay,
|
||||||
handleStretchXSphere,
|
handleStretchXCube,
|
||||||
handleStretchYSphere,
|
handleStretchYCube,
|
||||||
handleStretchZSphere,
|
handleStretchZCube,
|
||||||
handleStretchXPanel,
|
handleStretchXPanel,
|
||||||
handleStretchYPanel,
|
handleStretchYPanel,
|
||||||
handleStretchZPanel,
|
handleStretchZPanel,
|
||||||
handleScaleLBNCube,
|
handleScaleCube,
|
||||||
handleScaleRBNCube,
|
handleBoundingTREdge,
|
||||||
handleScaleLBFCube,
|
handleBoundingTLEdge,
|
||||||
handleScaleRBFCube,
|
handleBoundingTFEdge,
|
||||||
handleScaleLTNCube,
|
handleBoundingTNEdge,
|
||||||
handleScaleRTNCube,
|
handleBoundingBREdge,
|
||||||
handleScaleLTFCube,
|
handleBoundingBLEdge,
|
||||||
handleScaleRTFCube,
|
handleBoundingBFEdge,
|
||||||
handleScaleTREdge,
|
handleBoundingBNEdge,
|
||||||
handleScaleTLEdge,
|
handleBoundingNREdge,
|
||||||
handleScaleTFEdge,
|
handleBoundingNLEdge,
|
||||||
handleScaleTNEdge,
|
handleBoundingFREdge,
|
||||||
handleScaleBREdge,
|
handleBoundingFLEdge,
|
||||||
handleScaleBLEdge,
|
|
||||||
handleScaleBFEdge,
|
|
||||||
handleScaleBNEdge,
|
|
||||||
handleScaleNREdge,
|
|
||||||
handleScaleNLEdge,
|
|
||||||
handleScaleFREdge,
|
|
||||||
handleScaleFLEdge,
|
|
||||||
handleCloner,
|
handleCloner,
|
||||||
selectionBox,
|
selectionBox,
|
||||||
iconSelectionBox,
|
iconSelectionBox,
|
||||||
|
@ -787,34 +771,27 @@ SelectionDisplay = (function() {
|
||||||
overlayNames[handleRotateCurrentRing] = "handleRotateCurrentRing";
|
overlayNames[handleRotateCurrentRing] = "handleRotateCurrentRing";
|
||||||
overlayNames[rotationDegreesDisplay] = "rotationDegreesDisplay";
|
overlayNames[rotationDegreesDisplay] = "rotationDegreesDisplay";
|
||||||
|
|
||||||
overlayNames[handleStretchXSphere] = "handleStretchXSphere";
|
overlayNames[handleStretchXCube] = "handleStretchXCube";
|
||||||
overlayNames[handleStretchYSphere] = "handleStretchYSphere";
|
overlayNames[handleStretchYCube] = "handleStretchYCube";
|
||||||
overlayNames[handleStretchZSphere] = "handleStretchZSphere";
|
overlayNames[handleStretchZCube] = "handleStretchZCube";
|
||||||
overlayNames[handleStretchXPanel] = "handleStretchXPanel";
|
overlayNames[handleStretchXPanel] = "handleStretchXPanel";
|
||||||
overlayNames[handleStretchYPanel] = "handleStretchYPanel";
|
overlayNames[handleStretchYPanel] = "handleStretchYPanel";
|
||||||
overlayNames[handleStretchZPanel] = "handleStretchZPanel";
|
overlayNames[handleStretchZPanel] = "handleStretchZPanel";
|
||||||
|
|
||||||
overlayNames[handleScaleLBNCube] = "handleScaleLBNCube";
|
overlayNames[handleScaleCube] = "handleScaleCube";
|
||||||
overlayNames[handleScaleRBNCube] = "handleScaleRBNCube";
|
|
||||||
overlayNames[handleScaleLBFCube] = "handleScaleLBFCube";
|
|
||||||
overlayNames[handleScaleRBFCube] = "handleScaleRBFCube";
|
|
||||||
overlayNames[handleScaleLTNCube] = "handleScaleLTNCube";
|
|
||||||
overlayNames[handleScaleRTNCube] = "handleScaleRTNCube";
|
|
||||||
overlayNames[handleScaleLTFCube] = "handleScaleLTFCube";
|
|
||||||
overlayNames[handleScaleRTFCube] = "handleScaleRTFCube";
|
|
||||||
|
|
||||||
overlayNames[handleScaleTREdge] = "handleScaleTREdge";
|
overlayNames[handleBoundingTREdge] = "handleBoundingTREdge";
|
||||||
overlayNames[handleScaleTLEdge] = "handleScaleTLEdge";
|
overlayNames[handleBoundingTLEdge] = "handleBoundingTLEdge";
|
||||||
overlayNames[handleScaleTFEdge] = "handleScaleTFEdge";
|
overlayNames[handleBoundingTFEdge] = "handleBoundingTFEdge";
|
||||||
overlayNames[handleScaleTNEdge] = "handleScaleTNEdge";
|
overlayNames[handleBoundingTNEdge] = "handleBoundingTNEdge";
|
||||||
overlayNames[handleScaleBREdge] = "handleScaleBREdge";
|
overlayNames[handleBoundingBREdge] = "handleBoundingBREdge";
|
||||||
overlayNames[handleScaleBLEdge] = "handleScaleBLEdge";
|
overlayNames[handleBoundingBLEdge] = "handleBoundingBLEdge";
|
||||||
overlayNames[handleScaleBFEdge] = "handleScaleBFEdge";
|
overlayNames[handleBoundingBFEdge] = "handleBoundingBFEdge";
|
||||||
overlayNames[handleScaleBNEdge] = "handleScaleBNEdge";
|
overlayNames[handleBoundingBNEdge] = "handleBoundingBNEdge";
|
||||||
overlayNames[handleScaleNREdge] = "handleScaleNREdge";
|
overlayNames[handleBoundingNREdge] = "handleBoundingNREdge";
|
||||||
overlayNames[handleScaleNLEdge] = "handleScaleNLEdge";
|
overlayNames[handleBoundingNLEdge] = "handleBoundingNLEdge";
|
||||||
overlayNames[handleScaleFREdge] = "handleScaleFREdge";
|
overlayNames[handleBoundingFREdge] = "handleBoundingFREdge";
|
||||||
overlayNames[handleScaleFLEdge] = "handleScaleFLEdge";
|
overlayNames[handleBoundingFLEdge] = "handleBoundingFLEdge";
|
||||||
|
|
||||||
overlayNames[handleCloner] = "handleCloner";
|
overlayNames[handleCloner] = "handleCloner";
|
||||||
overlayNames[selectionBox] = "selectionBox";
|
overlayNames[selectionBox] = "selectionBox";
|
||||||
|
@ -1021,32 +998,25 @@ SelectionDisplay = (function() {
|
||||||
case handleTranslateXCone:
|
case handleTranslateXCone:
|
||||||
case handleTranslateXCylinder:
|
case handleTranslateXCylinder:
|
||||||
case handleRotatePitchRing:
|
case handleRotatePitchRing:
|
||||||
case handleStretchXSphere:
|
case handleStretchXCube:
|
||||||
pickedColor = COLOR_RED;
|
pickedColor = COLOR_RED;
|
||||||
highlightNeeded = true;
|
highlightNeeded = true;
|
||||||
break;
|
break;
|
||||||
case handleTranslateYCone:
|
case handleTranslateYCone:
|
||||||
case handleTranslateYCylinder:
|
case handleTranslateYCylinder:
|
||||||
case handleRotateYawRing:
|
case handleRotateYawRing:
|
||||||
case handleStretchYSphere:
|
case handleStretchYCube:
|
||||||
pickedColor = COLOR_GREEN;
|
pickedColor = COLOR_GREEN;
|
||||||
highlightNeeded = true;
|
highlightNeeded = true;
|
||||||
break;
|
break;
|
||||||
case handleTranslateZCone:
|
case handleTranslateZCone:
|
||||||
case handleTranslateZCylinder:
|
case handleTranslateZCylinder:
|
||||||
case handleRotateRollRing:
|
case handleRotateRollRing:
|
||||||
case handleStretchZSphere:
|
case handleStretchZCube:
|
||||||
pickedColor = COLOR_BLUE;
|
pickedColor = COLOR_BLUE;
|
||||||
highlightNeeded = true;
|
highlightNeeded = true;
|
||||||
break;
|
break;
|
||||||
case handleScaleLBNCube:
|
case handleScaleCube:
|
||||||
case handleScaleRBNCube:
|
|
||||||
case handleScaleLBFCube:
|
|
||||||
case handleScaleRBFCube:
|
|
||||||
case handleScaleLTNCube:
|
|
||||||
case handleScaleRTNCube:
|
|
||||||
case handleScaleLTFCube:
|
|
||||||
case handleScaleRTFCube:
|
|
||||||
pickedColor = COLOR_SCALE_CUBE;
|
pickedColor = COLOR_SCALE_CUBE;
|
||||||
highlightNeeded = true;
|
highlightNeeded = true;
|
||||||
break;
|
break;
|
||||||
|
@ -1424,127 +1394,56 @@ SelectionDisplay = (function() {
|
||||||
dimensions: arrowConeDimensions
|
dimensions: arrowConeDimensions
|
||||||
});
|
});
|
||||||
|
|
||||||
// UPDATE SCALE CUBES
|
// UPDATE SCALE CUBE
|
||||||
var scaleCubeOffsetX = SCALE_CUBE_OFFSET * dimensions.x;
|
var scaleCubeRotation = spaceMode === SPACE_LOCAL ? rotation : Quat.IDENTITY;
|
||||||
var scaleCubeOffsetY = SCALE_CUBE_OFFSET * dimensions.y;
|
var scaleCubeDimension = rotateDimension * SCALE_CUBE_CAMERA_DISTANCE_MULTIPLE /
|
||||||
var scaleCubeOffsetZ = SCALE_CUBE_OFFSET * dimensions.z;
|
|
||||||
var scaleCubeRotation = spaceMode === SPACE_LOCAL ? rotation : Quat.IDENTITY;
|
|
||||||
var scaleLBNCubePosition = { x: -scaleCubeOffsetX, y: -scaleCubeOffsetY, z: -scaleCubeOffsetZ };
|
|
||||||
scaleLBNCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleLBNCubePosition));
|
|
||||||
var scaleLBNCubeToCamera = getDistanceToCamera(scaleLBNCubePosition);
|
|
||||||
var scaleRBNCubePosition = { x: scaleCubeOffsetX, y: -scaleCubeOffsetY, z: -scaleCubeOffsetZ };
|
|
||||||
scaleRBNCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleRBNCubePosition));
|
|
||||||
var scaleRBNCubeToCamera = getDistanceToCamera(scaleRBNCubePosition);
|
|
||||||
var scaleLBFCubePosition = { x: -scaleCubeOffsetX, y: -scaleCubeOffsetY, z: scaleCubeOffsetZ };
|
|
||||||
scaleLBFCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleLBFCubePosition));
|
|
||||||
var scaleLBFCubeToCamera = getDistanceToCamera(scaleLBFCubePosition);
|
|
||||||
var scaleRBFCubePosition = { x: scaleCubeOffsetX, y: -scaleCubeOffsetY, z: scaleCubeOffsetZ };
|
|
||||||
scaleRBFCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleRBFCubePosition));
|
|
||||||
var scaleRBFCubeToCamera = getDistanceToCamera(scaleRBFCubePosition);
|
|
||||||
var scaleLTNCubePosition = { x: -scaleCubeOffsetX, y: scaleCubeOffsetY, z: -scaleCubeOffsetZ };
|
|
||||||
scaleLTNCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleLTNCubePosition));
|
|
||||||
var scaleLTNCubeToCamera = getDistanceToCamera(scaleLTNCubePosition);
|
|
||||||
var scaleRTNCubePosition = { x: scaleCubeOffsetX, y: scaleCubeOffsetY, z: -scaleCubeOffsetZ };
|
|
||||||
scaleRTNCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleRTNCubePosition));
|
|
||||||
var scaleRTNCubeToCamera = getDistanceToCamera(scaleRTNCubePosition);
|
|
||||||
var scaleLTFCubePosition = { x: -scaleCubeOffsetX, y: scaleCubeOffsetY, z: scaleCubeOffsetZ };
|
|
||||||
scaleLTFCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleLTFCubePosition));
|
|
||||||
var scaleLTFCubeToCamera = getDistanceToCamera(scaleLTFCubePosition);
|
|
||||||
var scaleRTFCubePosition = { x: scaleCubeOffsetX, y: scaleCubeOffsetY, z: scaleCubeOffsetZ };
|
|
||||||
scaleRTFCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleRTFCubePosition));
|
|
||||||
var scaleRTFCubeToCamera = getDistanceToCamera(scaleRTFCubePosition);
|
|
||||||
|
|
||||||
var scaleCubeToCamera = Math.min(scaleLBNCubeToCamera, scaleRBNCubeToCamera, scaleLBFCubeToCamera,
|
|
||||||
scaleRBFCubeToCamera, scaleLTNCubeToCamera, scaleRTNCubeToCamera,
|
|
||||||
scaleLTFCubeToCamera, scaleRTFCubeToCamera);
|
|
||||||
var scaleCubeDimension = scaleCubeToCamera * SCALE_CUBE_CAMERA_DISTANCE_MULTIPLE;
|
|
||||||
var scaleCubeDimensions = { x: scaleCubeDimension, y: scaleCubeDimension, z: scaleCubeDimension };
|
|
||||||
|
|
||||||
Overlays.editOverlay(handleScaleLBNCube, {
|
|
||||||
position: scaleLBNCubePosition,
|
|
||||||
rotation: scaleCubeRotation,
|
|
||||||
dimensions: scaleCubeDimensions
|
|
||||||
});
|
|
||||||
Overlays.editOverlay(handleScaleRBNCube, {
|
|
||||||
position: scaleRBNCubePosition,
|
|
||||||
rotation: scaleCubeRotation,
|
|
||||||
dimensions: scaleCubeDimensions
|
|
||||||
});
|
|
||||||
Overlays.editOverlay(handleScaleLBFCube, {
|
|
||||||
position: scaleLBFCubePosition,
|
|
||||||
rotation: scaleCubeRotation,
|
|
||||||
dimensions: scaleCubeDimensions
|
|
||||||
});
|
|
||||||
Overlays.editOverlay(handleScaleRBFCube, {
|
|
||||||
position: scaleRBFCubePosition,
|
|
||||||
rotation: scaleCubeRotation,
|
|
||||||
dimensions: scaleCubeDimensions
|
|
||||||
});
|
|
||||||
Overlays.editOverlay(handleScaleLTNCube, {
|
|
||||||
position: scaleLTNCubePosition,
|
|
||||||
rotation: scaleCubeRotation,
|
|
||||||
dimensions: scaleCubeDimensions
|
|
||||||
});
|
|
||||||
Overlays.editOverlay(handleScaleRTNCube, {
|
|
||||||
position: scaleRTNCubePosition,
|
|
||||||
rotation: scaleCubeRotation,
|
|
||||||
dimensions: scaleCubeDimensions
|
|
||||||
});
|
|
||||||
Overlays.editOverlay(handleScaleLTFCube, {
|
|
||||||
position: scaleLTFCubePosition,
|
|
||||||
rotation: scaleCubeRotation,
|
|
||||||
dimensions: scaleCubeDimensions
|
|
||||||
});
|
|
||||||
Overlays.editOverlay(handleScaleRTFCube, {
|
|
||||||
position: scaleRTFCubePosition,
|
|
||||||
rotation: scaleCubeRotation,
|
|
||||||
dimensions: scaleCubeDimensions
|
|
||||||
});
|
|
||||||
|
|
||||||
// UPDATE SCALE EDGES
|
|
||||||
Overlays.editOverlay(handleScaleTREdge, { start: scaleRTNCubePosition, end: scaleRTFCubePosition });
|
|
||||||
Overlays.editOverlay(handleScaleTLEdge, { start: scaleLTNCubePosition, end: scaleLTFCubePosition });
|
|
||||||
Overlays.editOverlay(handleScaleTFEdge, { start: scaleLTFCubePosition, end: scaleRTFCubePosition });
|
|
||||||
Overlays.editOverlay(handleScaleTNEdge, { start: scaleLTNCubePosition, end: scaleRTNCubePosition });
|
|
||||||
Overlays.editOverlay(handleScaleBREdge, { start: scaleRBNCubePosition, end: scaleRBFCubePosition });
|
|
||||||
Overlays.editOverlay(handleScaleBLEdge, { start: scaleLBNCubePosition, end: scaleLBFCubePosition });
|
|
||||||
Overlays.editOverlay(handleScaleBFEdge, { start: scaleLBFCubePosition, end: scaleRBFCubePosition });
|
|
||||||
Overlays.editOverlay(handleScaleBNEdge, { start: scaleLBNCubePosition, end: scaleRBNCubePosition });
|
|
||||||
Overlays.editOverlay(handleScaleNREdge, { start: scaleRTNCubePosition, end: scaleRBNCubePosition });
|
|
||||||
Overlays.editOverlay(handleScaleNLEdge, { start: scaleLTNCubePosition, end: scaleLBNCubePosition });
|
|
||||||
Overlays.editOverlay(handleScaleFREdge, { start: scaleRTFCubePosition, end: scaleRBFCubePosition });
|
|
||||||
Overlays.editOverlay(handleScaleFLEdge, { start: scaleLTFCubePosition, end: scaleLBFCubePosition });
|
|
||||||
|
|
||||||
// UPDATE STRETCH SPHERES
|
|
||||||
var stretchSphereDimension = rotateDimension * STRETCH_SPHERE_CAMERA_DISTANCE_MULTIPLE /
|
|
||||||
ROTATE_RING_CAMERA_DISTANCE_MULTIPLE;
|
ROTATE_RING_CAMERA_DISTANCE_MULTIPLE;
|
||||||
var stretchSphereDimensions = { x: stretchSphereDimension, y: stretchSphereDimension, z: stretchSphereDimension };
|
var scaleCubeDimensions = { x: scaleCubeDimension, y: scaleCubeDimension, z: scaleCubeDimension };
|
||||||
var stretchSphereOffset = rotateDimension * STRETCH_SPHERE_OFFSET / ROTATE_RING_CAMERA_DISTANCE_MULTIPLE;
|
Overlays.editOverlay(handleScaleCube, {
|
||||||
var stretchXPosition = { x: stretchSphereOffset, y: 0, z: 0 };
|
position: position,
|
||||||
stretchXPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, stretchXPosition));
|
rotation: scaleCubeRotation,
|
||||||
Overlays.editOverlay(handleStretchXSphere, {
|
dimensions: scaleCubeDimensions
|
||||||
position: stretchXPosition,
|
|
||||||
dimensions: stretchSphereDimensions
|
|
||||||
});
|
|
||||||
var stretchYPosition = { x: 0, y: stretchSphereOffset, z: 0 };
|
|
||||||
stretchYPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, stretchYPosition));
|
|
||||||
Overlays.editOverlay(handleStretchYSphere, {
|
|
||||||
position: stretchYPosition,
|
|
||||||
dimensions: stretchSphereDimensions
|
|
||||||
});
|
|
||||||
var stretchZPosition = { x: 0, y: 0, z: stretchSphereOffset };
|
|
||||||
stretchZPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, stretchZPosition));
|
|
||||||
Overlays.editOverlay(handleStretchZSphere, {
|
|
||||||
position: stretchZPosition,
|
|
||||||
dimensions: stretchSphereDimensions
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// UPDATE BOUNDING BOX EDGES
|
||||||
|
var edgeOffsetX = BOUNDING_EDGE_OFFSET * dimensions.x;
|
||||||
|
var edgeOffsetY = BOUNDING_EDGE_OFFSET * dimensions.y;
|
||||||
|
var edgeOffsetZ = BOUNDING_EDGE_OFFSET * dimensions.z;
|
||||||
|
var LBNPosition = { x: -edgeOffsetX, y: -edgeOffsetY, z: -edgeOffsetZ };
|
||||||
|
LBNPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, LBNPosition));
|
||||||
|
var RBNPosition = { x: edgeOffsetX, y: -edgeOffsetY, z: -edgeOffsetZ };
|
||||||
|
RBNPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, RBNPosition));
|
||||||
|
var LBFPosition = { x: -edgeOffsetX, y: -edgeOffsetY, z: edgeOffsetZ };
|
||||||
|
LBFPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, LBFPosition));
|
||||||
|
var RBFPosition = { x: edgeOffsetX, y: -edgeOffsetY, z: edgeOffsetZ };
|
||||||
|
RBFPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, RBFPosition));
|
||||||
|
var LTNPosition = { x: -edgeOffsetX, y: edgeOffsetY, z: -edgeOffsetZ };
|
||||||
|
LTNPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, LTNPosition));
|
||||||
|
var RTNPosition = { x: edgeOffsetX, y: edgeOffsetY, z: -edgeOffsetZ };
|
||||||
|
RTNPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, RTNPosition));
|
||||||
|
var LTFPosition = { x: -edgeOffsetX, y: edgeOffsetY, z: edgeOffsetZ };
|
||||||
|
LTFPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, LTFPosition));
|
||||||
|
var RTFPosition = { x: edgeOffsetX, y: edgeOffsetY, z: edgeOffsetZ };
|
||||||
|
RTFPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, RTFPosition));
|
||||||
|
Overlays.editOverlay(handleBoundingTREdge, { start: RTNPosition, end: RTFPosition });
|
||||||
|
Overlays.editOverlay(handleBoundingTLEdge, { start: LTNPosition, end: LTFPosition });
|
||||||
|
Overlays.editOverlay(handleBoundingTFEdge, { start: LTFPosition, end: RTFPosition });
|
||||||
|
Overlays.editOverlay(handleBoundingTNEdge, { start: LTNPosition, end: RTNPosition });
|
||||||
|
Overlays.editOverlay(handleBoundingBREdge, { start: RBNPosition, end: RBFPosition });
|
||||||
|
Overlays.editOverlay(handleBoundingBLEdge, { start: LBNPosition, end: LBFPosition });
|
||||||
|
Overlays.editOverlay(handleBoundingBFEdge, { start: LBFPosition, end: RBFPosition });
|
||||||
|
Overlays.editOverlay(handleBoundingBNEdge, { start: LBNPosition, end: RBNPosition });
|
||||||
|
Overlays.editOverlay(handleBoundingNREdge, { start: RTNPosition, end: RBNPosition });
|
||||||
|
Overlays.editOverlay(handleBoundingNLEdge, { start: LTNPosition, end: LBNPosition });
|
||||||
|
Overlays.editOverlay(handleBoundingFREdge, { start: RTFPosition, end: RBFPosition });
|
||||||
|
Overlays.editOverlay(handleBoundingFLEdge, { start: LTFPosition, end: LBFPosition });
|
||||||
|
|
||||||
// UPDATE STRETCH HIGHLIGHT PANELS
|
// UPDATE STRETCH HIGHLIGHT PANELS
|
||||||
var scaleRBFCubePositionRotated = Vec3.multiplyQbyV(rotationInverse, scaleRBFCubePosition);
|
var RBFPositionRotated = Vec3.multiplyQbyV(rotationInverse, RBFPosition);
|
||||||
var scaleRTFCubePositionRotated = Vec3.multiplyQbyV(rotationInverse, scaleRTFCubePosition);
|
var RTFPositionRotated = Vec3.multiplyQbyV(rotationInverse, RTFPosition);
|
||||||
var scaleLTNCubePositionRotated = Vec3.multiplyQbyV(rotationInverse, scaleLTNCubePosition);
|
var LTNPositionRotated = Vec3.multiplyQbyV(rotationInverse, LTNPosition);
|
||||||
var scaleRTNCubePositionRotated = Vec3.multiplyQbyV(rotationInverse, scaleRTNCubePosition);
|
var RTNPositionRotated = Vec3.multiplyQbyV(rotationInverse, RTNPosition);
|
||||||
var stretchPanelXDimensions = Vec3.subtract(scaleRTNCubePositionRotated, scaleRBFCubePositionRotated);
|
var stretchPanelXDimensions = Vec3.subtract(RTNPositionRotated, RBFPositionRotated);
|
||||||
var tempY = Math.abs(stretchPanelXDimensions.y);
|
var tempY = Math.abs(stretchPanelXDimensions.y);
|
||||||
stretchPanelXDimensions.x = STRETCH_PANEL_WIDTH;
|
stretchPanelXDimensions.x = STRETCH_PANEL_WIDTH;
|
||||||
stretchPanelXDimensions.y = Math.abs(stretchPanelXDimensions.z);
|
stretchPanelXDimensions.y = Math.abs(stretchPanelXDimensions.z);
|
||||||
|
@ -1555,7 +1454,7 @@ SelectionDisplay = (function() {
|
||||||
rotation: rotationZ,
|
rotation: rotationZ,
|
||||||
dimensions: stretchPanelXDimensions
|
dimensions: stretchPanelXDimensions
|
||||||
});
|
});
|
||||||
var stretchPanelYDimensions = Vec3.subtract(scaleLTNCubePositionRotated, scaleRTFCubePositionRotated);
|
var stretchPanelYDimensions = Vec3.subtract(LTNPositionRotated, RTFPositionRotated);
|
||||||
var tempX = Math.abs(stretchPanelYDimensions.x);
|
var tempX = Math.abs(stretchPanelYDimensions.x);
|
||||||
stretchPanelYDimensions.x = Math.abs(stretchPanelYDimensions.z);
|
stretchPanelYDimensions.x = Math.abs(stretchPanelYDimensions.z);
|
||||||
stretchPanelYDimensions.y = STRETCH_PANEL_WIDTH;
|
stretchPanelYDimensions.y = STRETCH_PANEL_WIDTH;
|
||||||
|
@ -1566,7 +1465,7 @@ SelectionDisplay = (function() {
|
||||||
rotation: rotationY,
|
rotation: rotationY,
|
||||||
dimensions: stretchPanelYDimensions
|
dimensions: stretchPanelYDimensions
|
||||||
});
|
});
|
||||||
var stretchPanelZDimensions = Vec3.subtract(scaleLTNCubePositionRotated, scaleRBFCubePositionRotated);
|
var stretchPanelZDimensions = Vec3.subtract(LTNPositionRotated, RBFPositionRotated);
|
||||||
tempX = Math.abs(stretchPanelZDimensions.x);
|
tempX = Math.abs(stretchPanelZDimensions.x);
|
||||||
stretchPanelZDimensions.x = Math.abs(stretchPanelZDimensions.y);
|
stretchPanelZDimensions.x = Math.abs(stretchPanelZDimensions.y);
|
||||||
stretchPanelZDimensions.y = tempX;
|
stretchPanelZDimensions.y = tempX;
|
||||||
|
@ -1578,6 +1477,46 @@ SelectionDisplay = (function() {
|
||||||
dimensions: stretchPanelZDimensions
|
dimensions: stretchPanelZDimensions
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// UPDATE STRETCH CUBES
|
||||||
|
var stretchCubeDimension = rotateDimension * STRETCH_CUBE_CAMERA_DISTANCE_MULTIPLE /
|
||||||
|
ROTATE_RING_CAMERA_DISTANCE_MULTIPLE;
|
||||||
|
var stretchCubeDimensions = { x: stretchCubeDimension, y: stretchCubeDimension, z: stretchCubeDimension };
|
||||||
|
var stretchCubeOffset = rotateDimension * STRETCH_CUBE_OFFSET / ROTATE_RING_CAMERA_DISTANCE_MULTIPLE;
|
||||||
|
var stretchXPosition, stretchYPosition, stretchZPosition;
|
||||||
|
if (isActiveTool(handleStretchXCube)) {
|
||||||
|
stretchXPosition = Vec3.subtract(stretchPanelXPosition, activeStretchCubePanelOffset);
|
||||||
|
} else {
|
||||||
|
stretchXPosition = { x: stretchCubeOffset, y: 0, z: 0 };
|
||||||
|
stretchXPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, stretchXPosition));
|
||||||
|
}
|
||||||
|
if (isActiveTool(handleStretchYCube)) {
|
||||||
|
stretchYPosition = Vec3.subtract(stretchPanelYPosition, activeStretchCubePanelOffset);
|
||||||
|
} else {
|
||||||
|
stretchYPosition = { x: 0, y: stretchCubeOffset, z: 0 };
|
||||||
|
stretchYPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, stretchYPosition));
|
||||||
|
}
|
||||||
|
if (isActiveTool(handleStretchZCube)) {
|
||||||
|
stretchZPosition = Vec3.subtract(stretchPanelZPosition, activeStretchCubePanelOffset);
|
||||||
|
} else {
|
||||||
|
stretchZPosition = { x: 0, y: 0, z: stretchCubeOffset };
|
||||||
|
stretchZPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, stretchZPosition));
|
||||||
|
}
|
||||||
|
Overlays.editOverlay(handleStretchXCube, {
|
||||||
|
position: stretchXPosition,
|
||||||
|
rotation: rotationX,
|
||||||
|
dimensions: stretchCubeDimensions
|
||||||
|
});
|
||||||
|
Overlays.editOverlay(handleStretchYCube, {
|
||||||
|
position: stretchYPosition,
|
||||||
|
rotation: rotationY,
|
||||||
|
dimensions: stretchCubeDimensions
|
||||||
|
});
|
||||||
|
Overlays.editOverlay(handleStretchZCube, {
|
||||||
|
position: stretchZPosition,
|
||||||
|
rotation: rotationZ,
|
||||||
|
dimensions: stretchCubeDimensions
|
||||||
|
});
|
||||||
|
|
||||||
// UPDATE SELECTION BOX (CURRENTLY INVISIBLE WITH 0 ALPHA FOR TRANSLATE XZ TOOL)
|
// UPDATE SELECTION BOX (CURRENTLY INVISIBLE WITH 0 ALPHA FOR TRANSLATE XZ TOOL)
|
||||||
var inModeRotate = isActiveTool(handleRotatePitchRing) ||
|
var inModeRotate = isActiveTool(handleRotatePitchRing) ||
|
||||||
isActiveTool(handleRotateYawRing) ||
|
isActiveTool(handleRotateYawRing) ||
|
||||||
|
@ -1622,20 +1561,15 @@ SelectionDisplay = (function() {
|
||||||
that.setHandleRotateRollVisible(!activeTool || isActiveTool(handleRotateRollRing));
|
that.setHandleRotateRollVisible(!activeTool || isActiveTool(handleRotateRollRing));
|
||||||
|
|
||||||
var showScaleStretch = !activeTool && SelectionManager.selections.length === 1 && spaceMode === SPACE_LOCAL;
|
var showScaleStretch = !activeTool && SelectionManager.selections.length === 1 && spaceMode === SPACE_LOCAL;
|
||||||
that.setHandleStretchXVisible(showScaleStretch || isActiveTool(handleStretchXSphere));
|
that.setHandleStretchXVisible(showScaleStretch || isActiveTool(handleStretchXCube));
|
||||||
that.setHandleStretchYVisible(showScaleStretch || isActiveTool(handleStretchYSphere));
|
that.setHandleStretchYVisible(showScaleStretch || isActiveTool(handleStretchYCube));
|
||||||
that.setHandleStretchZVisible(showScaleStretch || isActiveTool(handleStretchZSphere));
|
that.setHandleStretchZVisible(showScaleStretch || isActiveTool(handleStretchZCube));
|
||||||
that.setHandleScaleCubeVisible(showScaleStretch || isActiveTool(handleScaleLBNCube) ||
|
that.setHandleScaleCubeVisible(showScaleStretch || isActiveTool(handleScaleCube));
|
||||||
isActiveTool(handleScaleRBNCube) || isActiveTool(handleScaleLBFCube) ||
|
|
||||||
isActiveTool(handleScaleRBFCube) || isActiveTool(handleScaleLTNCube) ||
|
|
||||||
isActiveTool(handleScaleRTNCube) || isActiveTool(handleScaleLTFCube) ||
|
|
||||||
isActiveTool(handleScaleRTFCube) || isActiveTool(handleStretchXSphere) ||
|
|
||||||
isActiveTool(handleStretchYSphere) || isActiveTool(handleStretchZSphere));
|
|
||||||
|
|
||||||
var showOutlineForZone = (SelectionManager.selections.length === 1 &&
|
var showOutlineForZone = (SelectionManager.selections.length === 1 &&
|
||||||
typeof SelectionManager.savedProperties[SelectionManager.selections[0]] !== "undefined" &&
|
typeof SelectionManager.savedProperties[SelectionManager.selections[0]] !== "undefined" &&
|
||||||
SelectionManager.savedProperties[SelectionManager.selections[0]].type === "Zone");
|
SelectionManager.savedProperties[SelectionManager.selections[0]].type === "Zone");
|
||||||
that.setHandleScaleEdgeVisible(showOutlineForZone || (!isActiveTool(handleRotatePitchRing) &&
|
that.setHandleBoundingEdgeVisible(showOutlineForZone || (!isActiveTool(handleRotatePitchRing) &&
|
||||||
!isActiveTool(handleRotateYawRing) &&
|
!isActiveTool(handleRotateYawRing) &&
|
||||||
!isActiveTool(handleRotateRollRing)));
|
!isActiveTool(handleRotateRollRing)));
|
||||||
|
|
||||||
|
@ -1721,47 +1655,40 @@ SelectionDisplay = (function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
that.setHandleStretchXVisible = function(isVisible) {
|
that.setHandleStretchXVisible = function(isVisible) {
|
||||||
Overlays.editOverlay(handleStretchXSphere, { visible: isVisible });
|
Overlays.editOverlay(handleStretchXCube, { visible: isVisible });
|
||||||
};
|
};
|
||||||
|
|
||||||
that.setHandleStretchYVisible = function(isVisible) {
|
that.setHandleStretchYVisible = function(isVisible) {
|
||||||
Overlays.editOverlay(handleStretchYSphere, { visible: isVisible });
|
Overlays.editOverlay(handleStretchYCube, { visible: isVisible });
|
||||||
};
|
};
|
||||||
|
|
||||||
that.setHandleStretchZVisible = function(isVisible) {
|
that.setHandleStretchZVisible = function(isVisible) {
|
||||||
Overlays.editOverlay(handleStretchZSphere, { visible: isVisible });
|
Overlays.editOverlay(handleStretchZCube, { visible: isVisible });
|
||||||
};
|
};
|
||||||
|
|
||||||
// FUNCTION: SET HANDLE SCALE VISIBLE
|
// FUNCTION: SET HANDLE SCALE VISIBLE
|
||||||
that.setHandleScaleVisible = function(isVisible) {
|
that.setHandleScaleVisible = function(isVisible) {
|
||||||
that.setHandleScaleCubeVisible(isVisible);
|
that.setHandleScaleCubeVisible(isVisible);
|
||||||
that.setHandleScaleEdgeVisible(isVisible);
|
that.setHandleBoundingEdgeVisible(isVisible);
|
||||||
};
|
};
|
||||||
|
|
||||||
that.setHandleScaleCubeVisible = function(isVisible) {
|
that.setHandleScaleCubeVisible = function(isVisible) {
|
||||||
Overlays.editOverlay(handleScaleLBNCube, { visible: isVisible });
|
Overlays.editOverlay(handleScaleCube, { visible: isVisible });
|
||||||
Overlays.editOverlay(handleScaleRBNCube, { visible: isVisible });
|
|
||||||
Overlays.editOverlay(handleScaleLBFCube, { visible: isVisible });
|
|
||||||
Overlays.editOverlay(handleScaleRBFCube, { visible: isVisible });
|
|
||||||
Overlays.editOverlay(handleScaleLTNCube, { visible: isVisible });
|
|
||||||
Overlays.editOverlay(handleScaleRTNCube, { visible: isVisible });
|
|
||||||
Overlays.editOverlay(handleScaleLTFCube, { visible: isVisible });
|
|
||||||
Overlays.editOverlay(handleScaleRTFCube, { visible: isVisible });
|
|
||||||
};
|
};
|
||||||
|
|
||||||
that.setHandleScaleEdgeVisible = function(isVisible) {
|
that.setHandleBoundingEdgeVisible = function(isVisible) {
|
||||||
Overlays.editOverlay(handleScaleTREdge, { visible: isVisible });
|
Overlays.editOverlay(handleBoundingTREdge, { visible: isVisible });
|
||||||
Overlays.editOverlay(handleScaleTLEdge, { visible: isVisible });
|
Overlays.editOverlay(handleBoundingTLEdge, { visible: isVisible });
|
||||||
Overlays.editOverlay(handleScaleTFEdge, { visible: isVisible });
|
Overlays.editOverlay(handleBoundingTFEdge, { visible: isVisible });
|
||||||
Overlays.editOverlay(handleScaleTNEdge, { visible: isVisible });
|
Overlays.editOverlay(handleBoundingTNEdge, { visible: isVisible });
|
||||||
Overlays.editOverlay(handleScaleBREdge, { visible: isVisible });
|
Overlays.editOverlay(handleBoundingBREdge, { visible: isVisible });
|
||||||
Overlays.editOverlay(handleScaleBLEdge, { visible: isVisible });
|
Overlays.editOverlay(handleBoundingBLEdge, { visible: isVisible });
|
||||||
Overlays.editOverlay(handleScaleBFEdge, { visible: isVisible });
|
Overlays.editOverlay(handleBoundingBFEdge, { visible: isVisible });
|
||||||
Overlays.editOverlay(handleScaleBNEdge, { visible: isVisible });
|
Overlays.editOverlay(handleBoundingBNEdge, { visible: isVisible });
|
||||||
Overlays.editOverlay(handleScaleNREdge, { visible: isVisible });
|
Overlays.editOverlay(handleBoundingNREdge, { visible: isVisible });
|
||||||
Overlays.editOverlay(handleScaleNLEdge, { visible: isVisible });
|
Overlays.editOverlay(handleBoundingNLEdge, { visible: isVisible });
|
||||||
Overlays.editOverlay(handleScaleFREdge, { visible: isVisible });
|
Overlays.editOverlay(handleBoundingFREdge, { visible: isVisible });
|
||||||
Overlays.editOverlay(handleScaleFLEdge, { visible: isVisible });
|
Overlays.editOverlay(handleBoundingFLEdge, { visible: isVisible });
|
||||||
};
|
};
|
||||||
|
|
||||||
// FUNCTION: SET HANDLE CLONER VISIBLE
|
// FUNCTION: SET HANDLE CLONER VISIBLE
|
||||||
|
@ -2123,7 +2050,7 @@ SelectionDisplay = (function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
// TOOL DEFINITION: HANDLE STRETCH TOOL
|
// TOOL DEFINITION: HANDLE STRETCH TOOL
|
||||||
function makeStretchTool(stretchMode, directionEnum, directionVec, pivot, offset, stretchPanel, scaleHandle) {
|
function makeStretchTool(stretchMode, directionEnum, directionVec, pivot, offset, stretchPanel, cubeHandle) {
|
||||||
var directionFor3DStretch = directionVec;
|
var directionFor3DStretch = directionVec;
|
||||||
var distanceFor3DStretch = 0;
|
var distanceFor3DStretch = 0;
|
||||||
var DISTANCE_INFLUENCE_THRESHOLD = 1.2;
|
var DISTANCE_INFLUENCE_THRESHOLD = 1.2;
|
||||||
|
@ -2155,8 +2082,11 @@ SelectionDisplay = (function() {
|
||||||
var pickRayPosition3D = null;
|
var pickRayPosition3D = null;
|
||||||
var rotation = null;
|
var rotation = null;
|
||||||
var previousPickRay = null;
|
var previousPickRay = null;
|
||||||
|
var beginMouseEvent = null;
|
||||||
|
|
||||||
var onBegin = function(event, pickRay, pickResult) {
|
var onBegin = function(event, pickRay, pickResult) {
|
||||||
|
var proportional = directionEnum === STRETCH_DIRECTION.ALL;
|
||||||
|
|
||||||
var properties = Entities.getEntityProperties(SelectionManager.selections[0]);
|
var properties = Entities.getEntityProperties(SelectionManager.selections[0]);
|
||||||
initialProperties = properties;
|
initialProperties = properties;
|
||||||
rotation = (spaceMode === SPACE_LOCAL) ? properties.rotation : Quat.IDENTITY;
|
rotation = (spaceMode === SPACE_LOCAL) ? properties.rotation : Quat.IDENTITY;
|
||||||
|
@ -2244,9 +2174,7 @@ SelectionDisplay = (function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
planeNormal = Vec3.multiplyQbyV(rotation, planeNormal);
|
planeNormal = Vec3.multiplyQbyV(rotation, planeNormal);
|
||||||
lastPick = rayPlaneIntersection(pickRay,
|
lastPick = rayPlaneIntersection(pickRay, pickRayPosition, planeNormal);
|
||||||
pickRayPosition,
|
|
||||||
planeNormal);
|
|
||||||
|
|
||||||
var planeNormal3D = {
|
var planeNormal3D = {
|
||||||
x: 0,
|
x: 0,
|
||||||
|
@ -2274,10 +2202,7 @@ SelectionDisplay = (function() {
|
||||||
if (stretchPanel !== null) {
|
if (stretchPanel !== null) {
|
||||||
Overlays.editOverlay(stretchPanel, { visible: true });
|
Overlays.editOverlay(stretchPanel, { visible: true });
|
||||||
}
|
}
|
||||||
if (scaleHandle !== null) {
|
|
||||||
Overlays.editOverlay(scaleHandle, { color: COLOR_SCALE_CUBE_SELECTED });
|
|
||||||
}
|
|
||||||
|
|
||||||
var collisionToRemove = "myAvatar";
|
var collisionToRemove = "myAvatar";
|
||||||
if (properties.collidesWith.indexOf(collisionToRemove) > -1) {
|
if (properties.collidesWith.indexOf(collisionToRemove) > -1) {
|
||||||
var newCollidesWith = properties.collidesWith.replace(collisionToRemove, "");
|
var newCollidesWith = properties.collidesWith.replace(collisionToRemove, "");
|
||||||
|
@ -2285,16 +2210,20 @@ SelectionDisplay = (function() {
|
||||||
that.replaceCollisionsAfterStretch = true;
|
that.replaceCollisionsAfterStretch = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!proportional) {
|
||||||
|
var stretchCubePosition = Overlays.getProperty(cubeHandle, "position");
|
||||||
|
var stretchPanelPosition = Overlays.getProperty(stretchPanel, "position");
|
||||||
|
activeStretchCubePanelOffset = Vec3.subtract(stretchPanelPosition, stretchCubePosition);
|
||||||
|
}
|
||||||
|
|
||||||
previousPickRay = pickRay;
|
previousPickRay = pickRay;
|
||||||
|
beginMouseEvent = event;
|
||||||
};
|
};
|
||||||
|
|
||||||
var onEnd = function(event, reason) {
|
var onEnd = function(event, reason) {
|
||||||
if (stretchPanel !== null) {
|
if (stretchPanel !== null) {
|
||||||
Overlays.editOverlay(stretchPanel, { visible: false });
|
Overlays.editOverlay(stretchPanel, { visible: false });
|
||||||
}
|
}
|
||||||
if (scaleHandle !== null) {
|
|
||||||
Overlays.editOverlay(scaleHandle, { color: COLOR_SCALE_CUBE });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (that.replaceCollisionsAfterStretch) {
|
if (that.replaceCollisionsAfterStretch) {
|
||||||
var newCollidesWith = SelectionManager.savedProperties[SelectionManager.selections[0]].collidesWith;
|
var newCollidesWith = SelectionManager.savedProperties[SelectionManager.selections[0]].collidesWith;
|
||||||
|
@ -2302,6 +2231,8 @@ SelectionDisplay = (function() {
|
||||||
that.replaceCollisionsAfterStretch = false;
|
that.replaceCollisionsAfterStretch = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
activeStretchCubePanelOffset = null;
|
||||||
|
|
||||||
pushCommandForSelections();
|
pushCommandForSelections();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2351,34 +2282,27 @@ SelectionDisplay = (function() {
|
||||||
vector = grid.snapToSpacing(vector);
|
vector = grid.snapToSpacing(vector);
|
||||||
|
|
||||||
var changeInDimensions = Vec3.multiply(NEGATE_VECTOR, vec3Mult(localSigns, vector));
|
var changeInDimensions = Vec3.multiply(NEGATE_VECTOR, vec3Mult(localSigns, vector));
|
||||||
if (directionEnum === STRETCH_DIRECTION.ALL) {
|
|
||||||
var toCameraDistance = getDistanceToCamera(position);
|
|
||||||
var dimensionsMultiple = toCameraDistance * STRETCH_DIRECTION_ALL_CAMERA_DISTANCE_MULTIPLE;
|
|
||||||
changeInDimensions = Vec3.multiply(changeInDimensions, dimensionsMultiple);
|
|
||||||
}
|
|
||||||
|
|
||||||
var newDimensions;
|
var newDimensions;
|
||||||
if (proportional) {
|
if (proportional) {
|
||||||
var absoluteX = Math.abs(changeInDimensions.x);
|
var viewportDimensions = Controller.getViewportDimensions();
|
||||||
var absoluteY = Math.abs(changeInDimensions.y);
|
var mouseXDifference = (event.x - beginMouseEvent.x) / viewportDimensions.x;
|
||||||
var absoluteZ = Math.abs(changeInDimensions.z);
|
var mouseYDifference = (beginMouseEvent.y - event.y) / viewportDimensions.y;
|
||||||
var percentChange = 0;
|
var mouseDifference = mouseXDifference + mouseYDifference;
|
||||||
if (absoluteX > absoluteY && absoluteX > absoluteZ) {
|
var toCameraDistance = getDistanceToCamera(position);
|
||||||
percentChange = changeInDimensions.x / initialProperties.dimensions.x;
|
var dimensionsMultiple = toCameraDistance * STRETCH_DIRECTION_ALL_CAMERA_DISTANCE_MULTIPLE;
|
||||||
percentChange = changeInDimensions.x / initialDimensions.x;
|
var dimensionChange = mouseDifference * dimensionsMultiple;
|
||||||
} else if (absoluteY > absoluteZ) {
|
var averageInitialDimension = (initialDimensions.x + initialDimensions.y + initialDimensions.z) / 3;
|
||||||
percentChange = changeInDimensions.y / initialProperties.dimensions.y;
|
percentChange = dimensionChange / averageInitialDimension;
|
||||||
percentChange = changeInDimensions.y / initialDimensions.y;
|
|
||||||
} else {
|
|
||||||
percentChange = changeInDimensions.z / initialProperties.dimensions.z;
|
|
||||||
percentChange = changeInDimensions.z / initialDimensions.z;
|
|
||||||
}
|
|
||||||
percentChange += 1.0;
|
percentChange += 1.0;
|
||||||
newDimensions = Vec3.multiply(percentChange, initialDimensions);
|
newDimensions = Vec3.multiply(percentChange, initialDimensions);
|
||||||
|
newDimensions.x = Math.abs(newDimensions.x);
|
||||||
|
newDimensions.y = Math.abs(newDimensions.y);
|
||||||
|
newDimensions.z = Math.abs(newDimensions.z);
|
||||||
} else {
|
} else {
|
||||||
newDimensions = Vec3.sum(initialDimensions, changeInDimensions);
|
newDimensions = Vec3.sum(initialDimensions, changeInDimensions);
|
||||||
}
|
}
|
||||||
|
|
||||||
var minimumDimension = directionEnum ===
|
var minimumDimension = directionEnum ===
|
||||||
STRETCH_DIRECTION.ALL ? STRETCH_ALL_MINIMUM_DIMENSION : STRETCH_MINIMUM_DIMENSION;
|
STRETCH_DIRECTION.ALL ? STRETCH_ALL_MINIMUM_DIMENSION : STRETCH_MINIMUM_DIMENSION;
|
||||||
if (newDimensions.x < minimumDimension) {
|
if (newDimensions.x < minimumDimension) {
|
||||||
|
@ -2393,9 +2317,9 @@ SelectionDisplay = (function() {
|
||||||
newDimensions.z = minimumDimension;
|
newDimensions.z = minimumDimension;
|
||||||
changeInDimensions.z = minimumDimension - initialDimensions.z;
|
changeInDimensions.z = minimumDimension - initialDimensions.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
var changeInPosition = Vec3.multiplyQbyV(rotation, vec3Mult(localDeltaPivot, changeInDimensions));
|
var changeInPosition = Vec3.multiplyQbyV(rotation, vec3Mult(localDeltaPivot, changeInDimensions));
|
||||||
if (directionEnum === STRETCH_DIRECTION.ALL) {
|
if (proportional) {
|
||||||
changeInPosition = { x: 0, y: 0, z: 0 };
|
changeInPosition = { x: 0, y: 0, z: 0 };
|
||||||
}
|
}
|
||||||
var newPosition = Vec3.sum(initialPosition, changeInPosition);
|
var newPosition = Vec3.sum(initialPosition, changeInPosition);
|
||||||
|
@ -2429,52 +2353,30 @@ SelectionDisplay = (function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function addHandleStretchTool(overlay, mode, directionEnum) {
|
function addHandleStretchTool(overlay, mode, directionEnum) {
|
||||||
var directionVector, offset, stretchPanel;
|
var directionVector, offset, stretchPanel, handleStretchCube;
|
||||||
if (directionEnum === STRETCH_DIRECTION.X) {
|
if (directionEnum === STRETCH_DIRECTION.X) {
|
||||||
stretchPanel = handleStretchXPanel;
|
stretchPanel = handleStretchXPanel;
|
||||||
|
handleStretchCube = handleStretchXCube;
|
||||||
directionVector = { x: -1, y: 0, z: 0 };
|
directionVector = { x: -1, y: 0, z: 0 };
|
||||||
} else if (directionEnum === STRETCH_DIRECTION.Y) {
|
} else if (directionEnum === STRETCH_DIRECTION.Y) {
|
||||||
stretchPanel = handleStretchYPanel;
|
stretchPanel = handleStretchYPanel;
|
||||||
|
handleStretchCube = handleStretchYCube;
|
||||||
directionVector = { x: 0, y: -1, z: 0 };
|
directionVector = { x: 0, y: -1, z: 0 };
|
||||||
} else if (directionEnum === STRETCH_DIRECTION.Z) {
|
} else if (directionEnum === STRETCH_DIRECTION.Z) {
|
||||||
stretchPanel = handleStretchZPanel;
|
stretchPanel = handleStretchZPanel;
|
||||||
|
handleStretchCube = handleStretchZCube;
|
||||||
directionVector = { x: 0, y: 0, z: -1 };
|
directionVector = { x: 0, y: 0, z: -1 };
|
||||||
}
|
}
|
||||||
offset = Vec3.multiply(directionVector, NEGATE_VECTOR);
|
offset = Vec3.multiply(directionVector, NEGATE_VECTOR);
|
||||||
var tool = makeStretchTool(mode, directionEnum, directionVector, directionVector, offset, stretchPanel, null);
|
var tool = makeStretchTool(mode, directionEnum, directionVector, directionVector, offset, stretchPanel, handleStretchCube);
|
||||||
return addHandleTool(overlay, tool);
|
return addHandleTool(overlay, tool);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TOOL DEFINITION: HANDLE SCALE TOOL
|
// TOOL DEFINITION: HANDLE SCALE TOOL
|
||||||
function addHandleScaleTool(overlay, mode, directionEnum) {
|
function addHandleScaleTool(overlay, mode) {
|
||||||
var directionVector, offset, selectedHandle;
|
var directionVector = { x:0, y:0, z:0 };
|
||||||
if (directionEnum === SCALE_DIRECTION.LBN) {
|
var offset = { x:0, y:0, z:0 };
|
||||||
directionVector = { x: 1, y: 1, z: 1 };
|
var tool = makeStretchTool(mode, STRETCH_DIRECTION.ALL, directionVector, directionVector, offset, null, handleScaleCube);
|
||||||
selectedHandle = handleScaleLBNCube;
|
|
||||||
} else if (directionEnum === SCALE_DIRECTION.RBN) {
|
|
||||||
directionVector = { x: -1, y: 1, z: 1 };
|
|
||||||
selectedHandle = handleScaleRBNCube;
|
|
||||||
} else if (directionEnum === SCALE_DIRECTION.LBF) {
|
|
||||||
directionVector = { x: 1, y: 1, z: -1 };
|
|
||||||
selectedHandle = handleScaleLBFCube;
|
|
||||||
} else if (directionEnum === SCALE_DIRECTION.RBF) {
|
|
||||||
directionVector = { x: -1, y: 1, z: -1 };
|
|
||||||
selectedHandle = handleScaleRBFCube;
|
|
||||||
} else if (directionEnum === SCALE_DIRECTION.LTN) {
|
|
||||||
directionVector = { x: 1, y: -1, z: 1 };
|
|
||||||
selectedHandle = handleScaleLTNCube;
|
|
||||||
} else if (directionEnum === SCALE_DIRECTION.RTN) {
|
|
||||||
directionVector = { x: -1, y: -1, z: 1 };
|
|
||||||
selectedHandle = handleScaleRTNCube;
|
|
||||||
} else if (directionEnum === SCALE_DIRECTION.LTF) {
|
|
||||||
directionVector = { x: 1, y: -1, z: -1 };
|
|
||||||
selectedHandle = handleScaleLTFCube;
|
|
||||||
} else if (directionEnum === SCALE_DIRECTION.RTF) {
|
|
||||||
directionVector = { x: -1, y: -1, z: -1 };
|
|
||||||
selectedHandle = handleScaleRTFCube;
|
|
||||||
}
|
|
||||||
offset = Vec3.multiply(directionVector, NEGATE_VECTOR);
|
|
||||||
var tool = makeStretchTool(mode, STRETCH_DIRECTION.ALL, directionVector, directionVector, offset, null, selectedHandle);
|
|
||||||
return addHandleTool(overlay, tool);
|
return addHandleTool(overlay, tool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2747,18 +2649,11 @@ SelectionDisplay = (function() {
|
||||||
addHandleRotateTool(handleRotateYawRing, "ROTATE_YAW", ROTATE_DIRECTION.YAW);
|
addHandleRotateTool(handleRotateYawRing, "ROTATE_YAW", ROTATE_DIRECTION.YAW);
|
||||||
addHandleRotateTool(handleRotateRollRing, "ROTATE_ROLL", ROTATE_DIRECTION.ROLL);
|
addHandleRotateTool(handleRotateRollRing, "ROTATE_ROLL", ROTATE_DIRECTION.ROLL);
|
||||||
|
|
||||||
addHandleStretchTool(handleStretchXSphere, "STRETCH_X", STRETCH_DIRECTION.X);
|
addHandleStretchTool(handleStretchXCube, "STRETCH_X", STRETCH_DIRECTION.X);
|
||||||
addHandleStretchTool(handleStretchYSphere, "STRETCH_Y", STRETCH_DIRECTION.Y);
|
addHandleStretchTool(handleStretchYCube, "STRETCH_Y", STRETCH_DIRECTION.Y);
|
||||||
addHandleStretchTool(handleStretchZSphere, "STRETCH_Z", STRETCH_DIRECTION.Z);
|
addHandleStretchTool(handleStretchZCube, "STRETCH_Z", STRETCH_DIRECTION.Z);
|
||||||
|
|
||||||
addHandleScaleTool(handleScaleLBNCube, "SCALE_LBN", SCALE_DIRECTION.LBN);
|
|
||||||
addHandleScaleTool(handleScaleRBNCube, "SCALE_RBN", SCALE_DIRECTION.RBN);
|
|
||||||
addHandleScaleTool(handleScaleLBFCube, "SCALE_LBF", SCALE_DIRECTION.LBF);
|
|
||||||
addHandleScaleTool(handleScaleRBFCube, "SCALE_RBF", SCALE_DIRECTION.RBF);
|
|
||||||
addHandleScaleTool(handleScaleLTNCube, "SCALE_LTN", SCALE_DIRECTION.LTN);
|
|
||||||
addHandleScaleTool(handleScaleRTNCube, "SCALE_RTN", SCALE_DIRECTION.RTN);
|
|
||||||
addHandleScaleTool(handleScaleLTFCube, "SCALE_LTF", SCALE_DIRECTION.LTF);
|
|
||||||
addHandleScaleTool(handleScaleRTFCube, "SCALE_RTF", SCALE_DIRECTION.RTF);
|
|
||||||
|
|
||||||
|
addHandleScaleTool(handleScaleCube, "SCALE");
|
||||||
|
|
||||||
return that;
|
return that;
|
||||||
}());
|
}());
|
||||||
|
|