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

This commit is contained in:
Gabriel Calero 2018-03-30 15:38:36 -03:00
commit b123b67134
48 changed files with 804 additions and 544 deletions

View file

@ -39,6 +39,7 @@ set(BUILD_TOOLS_OPTION ON)
set(BUILD_INSTALLER_OPTION ON)
set(GLES_OPTION OFF)
set(DISABLE_QML_OPTION OFF)
set(DOWNLOAD_SERVERLESS_CONTENT_OPTION OFF)
if (ANDROID OR UWP)
set(BUILD_SERVER_OPTION OFF)
@ -74,6 +75,11 @@ option(BUILD_INSTALLER "Build installer" ${BUILD_INSTALLER_OPTION})
option(USE_GLES "Use OpenGL ES" ${GLES_OPTION})
option(DISABLE_QML "Disable QML" ${DISABLE_QML_OPTION})
option(DISABLE_KTX_CACHE "Disable KTX Cache" OFF)
option(
DOWNLOAD_SERVERLESS_CONTENT
"Download and setup default serverless content beside Interface"
${DOWNLOAD_SERVERLESS_CONTENT_OPTION}
)
set(PLATFORM_QT_GL OpenGL)
@ -88,12 +94,13 @@ foreach(PLATFORM_QT_COMPONENT ${PLATFORM_QT_COMPONENTS})
list(APPEND PLATFORM_QT_LIBRARIES "Qt5::${PLATFORM_QT_COMPONENT}")
endforeach()
MESSAGE(STATUS "Build server: " ${BUILD_SERVER})
MESSAGE(STATUS "Build client: " ${BUILD_CLIENT})
MESSAGE(STATUS "Build tests: " ${BUILD_TESTS})
MESSAGE(STATUS "Build tools: " ${BUILD_TOOLS})
MESSAGE(STATUS "Build installer: " ${BUILD_INSTALLER})
MESSAGE(STATUS "GL ES: " ${USE_GLES})
MESSAGE(STATUS "Build server: " ${BUILD_SERVER})
MESSAGE(STATUS "Build client: " ${BUILD_CLIENT})
MESSAGE(STATUS "Build tests: " ${BUILD_TESTS})
MESSAGE(STATUS "Build tools: " ${BUILD_TOOLS})
MESSAGE(STATUS "Build installer: " ${BUILD_INSTALLER})
MESSAGE(STATUS "GL ES: " ${USE_GLES})
MESSAGE(STATUS "DL serverless content: " ${DOWNLOAD_SERVERLESS_CONTENT})
if (DISABLE_QML)
MESSAGE(STATUS "QML disabled!")

View file

@ -0,0 +1,16 @@
include(ExternalProject)
set(EXTERNAL_NAME serverless-content)
ExternalProject_Add(
${EXTERNAL_NAME}
URL http://cdn.highfidelity.com/content-sets/serverless-tutorial-RC66.zip
URL_MD5 91edfde96e06efc847ca327ab97f4c74
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
LOG_DOWNLOAD 1
)
# Hide this external target (for IDE users)
set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals")

View file

@ -73,6 +73,11 @@ macro(SET_PACKAGING_PARAMETERS)
add_definitions(-DDEV_BUILD)
endif ()
if (DEPLOY_PACKAGE)
# for deployed packages always grab the serverless content
set(DOWNLOAD_SERVERLESS_CONTENT ON)
endif ()
if (APPLE)
set(DMG_SUBFOLDER_NAME "${BUILD_ORGANIZATION}")

View file

@ -43,7 +43,6 @@ endif()
list(APPEND GENERATE_QRC_DEPENDS ${RESOURCES_RCC})
add_custom_target(resources ALL DEPENDS ${GENERATE_QRC_DEPENDS})
# set a default root dir for each of our optional externals if it was not passed
set(OPTIONAL_EXTERNALS "LeapMotion")
@ -314,35 +313,41 @@ if (APPLE)
)
set(SCRIPTS_INSTALL_DIR "${INTERFACE_INSTALL_APP_PATH}/Contents/Resources")
set(RESOURCES_DEV_DIR "$<TARGET_FILE_DIR:${TARGET_NAME}>/../Resources")
# copy script files beside the executable
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E copy_directory
"${CMAKE_SOURCE_DIR}/scripts"
"$<TARGET_FILE_DIR:${TARGET_NAME}>/../Resources/scripts"
"${RESOURCES_DEV_DIR}/scripts"
)
# call the fixup_interface macro to add required bundling commands for installation
fixup_interface()
else()
set(INTERFACE_EXEC_DIR "$<TARGET_FILE_DIR:${TARGET_NAME}>")
set(RESOURCES_DEV_DIR "${INTERFACE_EXEC_DIR}/resources")
# copy the resources files beside the executable
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
"${RESOURCES_RCC}"
"$<TARGET_FILE_DIR:interface>"
"${RESOURCES_RCC}"
"${INTERFACE_EXEC_DIR}"
# FIXME, the edit script code loads HTML from the scripts folder
# which in turn relies on CSS that refers to the fonts. In theory
# we should be able to modify the CSS to reference the QRC path to
# the ttf files, but doing so generates a CORS policy violation,
# so we have to retain a copy of the fonts outside of the resources binary
COMMAND "${CMAKE_COMMAND}" -E copy_directory
"${PROJECT_SOURCE_DIR}/resources/fonts"
"$<TARGET_FILE_DIR:${TARGET_NAME}>/resources/fonts"
"${PROJECT_SOURCE_DIR}/resources/fonts"
"${RESOURCES_DEV_DIR}/fonts"
COMMAND "${CMAKE_COMMAND}" -E copy_directory
"${CMAKE_SOURCE_DIR}/scripts"
"$<TARGET_FILE_DIR:${TARGET_NAME}>/scripts"
"${CMAKE_SOURCE_DIR}/scripts"
"${INTERFACE_EXEC_DIR}/scripts"
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
"${PROJECT_SOURCE_DIR}/resources/serverless/tutorial.json"
"${RESOURCES_DEV_DIR}/serverless/tutorial.json"
)
# link target to external libraries
@ -368,7 +373,6 @@ else()
endif()
if (SCRIPTS_INSTALL_DIR)
# setup install of scripts beside interface executable
install(
DIRECTORY "${CMAKE_SOURCE_DIR}/scripts/"
@ -377,6 +381,19 @@ if (SCRIPTS_INSTALL_DIR)
)
endif()
if (DOWNLOAD_SERVERLESS_CONTENT)
add_dependency_external_projects(serverless-content)
ExternalProject_Get_Property(serverless-content SOURCE_DIR)
# for dev builds, copy the serverless content to the resources folder
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E copy_directory
"${SOURCE_DIR}"
"${RESOURCES_DEV_DIR}/serverless"
)
endif ()
if (WIN32)
set(EXTRA_DEPLOY_OPTIONS "--qmldir \"${PROJECT_SOURCE_DIR}/resources/qml\"")

View file

@ -1,15 +1,10 @@
{
"name": "Keyboard/Mouse to Actions",
"channels": [
{ "from": "Keyboard.A", "when": "Keyboard.Shift", "to": "Actions.LATERAL_LEFT" },
{ "from": "Keyboard.D", "when": "Keyboard.Shift", "to": "Actions.LATERAL_RIGHT" },
{ "from": "Keyboard.A", "when": "Keyboard.RightMouseButton", "to": "Actions.LATERAL_LEFT" },
{ "from": "Keyboard.D", "when": "Keyboard.RightMouseButton", "to": "Actions.LATERAL_RIGHT" },
{ "from": "Keyboard.E", "when": "Keyboard.Shift", "to": "Actions.BOOM_IN", "filters": [ { "type": "scale", "scale": 0.05 } ] },
{ "from": "Keyboard.C", "when": "Keyboard.Shift", "to": "Actions.BOOM_OUT", "filters": [ { "type": "scale", "scale": 0.05 } ] },
{ "from": "Keyboard.S", "when": "Keyboard.Shift", "to": "Actions.PITCH_DOWN" },
{ "from": "Keyboard.W", "when": "Keyboard.Shift", "to": "Actions.PITCH_UP" },
{ "from": "Keyboard.E", "to": "Actions.LATERAL_RIGHT" },
{ "from": "Keyboard.Q", "to": "Actions.LATERAL_LEFT" },
{ "comment" : "Mouse turn need to be small continuous increments",
@ -44,9 +39,24 @@
]
},
{ "from": { "makeAxis" : [
["Keyboard.A", "Keyboard.Left" ],
["Keyboard.D", "Keyboard.Right"]
["Keyboard.Left" ],
["Keyboard.Right"]
]
},
"when": ["Application.InHMD", "Application.SnapTurn", "!Keyboard.Shift"],
"to": "Actions.StepYaw",
"filters":
[
{ "type": "pulse", "interval": 0.5, "resetOnZero": true },
{ "type": "scale", "scale": 22.5 }
]
},
{ "from": { "makeAxis" : [
["Keyboard.A"],
["Keyboard.D"]
]
},
"when": [ "Application.InHMD", "Application.SnapTurn" ],
@ -59,26 +69,39 @@
},
{ "from": { "makeAxis" : [
["Keyboard.A", "Keyboard.Left", "Keyboard.TouchpadLeft"],
["Keyboard.D", "Keyboard.Right", "Keyboard.TouchpadRight"]
["Keyboard.Left"],
["Keyboard.Right"]
]
},
"when": ["Application.CameraFirstPerson", "!Keyboard.Shift"],
"to": "Actions.Yaw"
},
{ "from": { "makeAxis" : [
["Keyboard.Left"],
["Keyboard.Right"]
]
},
"when": ["Application.CameraThirdPerson", "!Keyboard.Shift"],
"to": "Actions.Yaw"
},
{ "from": { "makeAxis" : [
["Keyboard.A", "Keyboard.TouchpadLeft"],
["Keyboard.D", "Keyboard.TouchpadRight"]
]
},
"when": "Application.CameraFirstPerson",
"to": "Actions.Yaw"
},
{ "from": { "makeAxis" : [
["Keyboard.A", "Keyboard.Left", "Keyboard.TouchpadLeft"],
["Keyboard.D", "Keyboard.Right", "Keyboard.TouchpadRight"]
["Keyboard.A", "Keyboard.TouchpadLeft"],
["Keyboard.D", "Keyboard.TouchpadRight"]
]
},
"when": "Application.CameraThirdPerson",
"to": "Actions.Yaw"
},
{ "from": { "makeAxis" : [ ["Keyboard.A"], ["Keyboard.D"] ] },
"when": "Application.CameraFSM",
"to": "Actions.Yaw"
},
{ "from": { "makeAxis" : ["Keyboard.MouseMoveLeft", "Keyboard.MouseMoveRight"] },
"when": "Keyboard.RightMouseButton",
"to": "Actions.Yaw",
@ -90,14 +113,10 @@
{ "from": "Keyboard.W", "when": "!Keyboard.Control", "to": "Actions.LONGITUDINAL_FORWARD" },
{ "from": "Keyboard.S", "when": "!Keyboard.Control", "to": "Actions.LONGITUDINAL_BACKWARD" },
{ "from": "Keyboard.C", "to": "Actions.VERTICAL_DOWN" },
{ "from": "Keyboard.E", "to": "Actions.VERTICAL_UP" },
{ "from": "Keyboard.Left", "when": "Keyboard.RightMouseButton", "to": "Actions.LATERAL_LEFT" },
{ "from": "Keyboard.Right", "when": "Keyboard.RightMouseButton", "to": "Actions.LATERAL_RIGHT" },
{ "from": "Keyboard.Shift", "when": ["!Keyboard.Left", "!Keyboard.Right"], "to": "Actions.SPRINT" },
{ "from": "Keyboard.Control", "to": "Actions.VERTICAL_DOWN" },
{ "from": "Keyboard.Left", "when": "Keyboard.Shift", "to": "Actions.LATERAL_LEFT" },
{ "from": "Keyboard.Right", "when": "Keyboard.Shift", "to": "Actions.LATERAL_RIGHT" },
{ "from": "Keyboard.Down", "when": "Keyboard.Shift", "to": "Actions.PITCH_DOWN" },
{ "from": "Keyboard.Up", "when": "Keyboard.Shift", "to": "Actions.PITCH_UP" },
{ "from": "Keyboard.Up", "when": "Application.CameraFirstPerson", "to": "Actions.LONGITUDINAL_FORWARD" },
{ "from": "Keyboard.Up", "when": "Application.CameraThirdPerson", "to": "Actions.LONGITUDINAL_FORWARD" },
{ "from": "Keyboard.Down", "when": "Application.CameraFirstPerson", "to": "Actions.LONGITUDINAL_BACKWARD" },
@ -128,7 +147,7 @@
{ "from": "Keyboard.MouseWheelLeft", "to": "Actions.BOOM_OUT", "filters": [ { "type": "scale", "scale": 0.02 } ]},
{ "from": "Keyboard.MouseWheelRight", "to": "Actions.BOOM_IN", "filters": [ { "type": "scale", "scale": 0.02 } ]},
{ "from": "Keyboard.Space", "to": "Actions.SHIFT" },
{ "from": "Keyboard.Space", "to": "Actions.VERTICAL_UP" },
{ "from": "Keyboard.R", "to": "Actions.ACTION1" },
{ "from": "Keyboard.T", "to": "Actions.ACTION2" },
{ "from": "Keyboard.Tab", "to": "Actions.ContextMenu" }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 215 KiB

After

Width:  |  Height:  |  Size: 241 KiB

View file

@ -67,6 +67,10 @@ Item {
fill: parent
}
MouseArea {
anchors.fill: parent
}
QmlHifi.WindowHeader {
id: header
iconSource: "../../../icons/goto-i.svg"

View file

@ -270,7 +270,9 @@ ModalWindow {
onTriggered: {
root.result = null;
root.canceled();
root.destroy();
// FIXME we are leaking memory to avoid a crash
// root.destroy();
visible = false;
}
}
@ -292,7 +294,9 @@ ModalWindow {
}
root.result = JSON.stringify(result);
root.selected(root.result);
root.destroy();
// FIXME we are leaking memory to avoid a crash
// root.destroy();
visible = false;
}
}
}

View file

@ -169,7 +169,9 @@ ModalWindow {
shortcut: Qt.Key_Escape
onTriggered: {
root.canceled();
root.destroy();
// FIXME we are leaking memory to avoid a crash
// root.destroy();
visible = false;
}
}
Action {
@ -179,7 +181,9 @@ ModalWindow {
onTriggered: {
root.result = items ? comboBox.currentText : textResult.text
root.selected(root.result);
root.destroy();
// FIXME we are leaking memory to avoid a crash
// root.destroy();
visible = false;
}
}
}

View file

@ -58,6 +58,10 @@ Item {
width: parent ? parent.width : 0
height: parent ? parent.height : 0
MouseArea {
anchors.fill: parent
}
gradient: Gradient {
GradientStop { position: 0.0; color: android.color.gradientTop }
GradientStop { position: 1.0; color: android.color.gradientBottom }

View file

@ -118,7 +118,7 @@ Item {
tabletRoot.playButtonClickSound();
}*/
}
onEntered: {
onPressed: {
button.isEntered = true;
button.entered();
if (button.isActive) {
@ -127,7 +127,7 @@ Item {
button.state = "hover state";
}
}
onExited: {
onReleased: {
button.isEntered = false;
button.exited()
if (button.isActive) {

View file

@ -24,6 +24,7 @@ Windows.ScrollingWindow {
objectName: "AssetServer"
title: "Asset Browser"
resizable: true
opacity: parent.opacity
destroyOnHidden: true
implicitWidth: 384; implicitHeight: 640
minSize: Qt.vector2d(200, 300)
@ -57,7 +58,7 @@ Windows.ScrollingWindow {
Component.onDestruction: {
assetMappingsModel.autoRefreshEnabled = false;
}
function letterbox(headerGlyph, headerText, message) {
letterboxMessage.headerGlyph = headerGlyph;
letterboxMessage.headerText = headerText;
@ -144,7 +145,7 @@ Windows.ScrollingWindow {
function canAddToWorld(path) {
var supportedExtensions = [/\.fbx\b/i, /\.obj\b/i, /\.jpg\b/i, /\.png\b/i];
if (selectedItemCount > 1) {
return false;
}
@ -153,8 +154,8 @@ Windows.ScrollingWindow {
return total | new RegExp(current).test(path);
}, false);
}
function canRename() {
function canRename() {
if (treeView.selection.hasSelection && selectedItemCount == 1) {
return true;
} else {
@ -198,7 +199,7 @@ Windows.ScrollingWindow {
var SHAPE_TYPE_STATIC_MESH = 3;
var SHAPE_TYPE_BOX = 4;
var SHAPE_TYPE_SPHERE = 5;
var SHAPE_TYPES = [];
SHAPE_TYPES[SHAPE_TYPE_NONE] = "No Collision";
SHAPE_TYPES[SHAPE_TYPE_SIMPLE_HULL] = "Basic - Whole model";
@ -206,7 +207,7 @@ Windows.ScrollingWindow {
SHAPE_TYPES[SHAPE_TYPE_STATIC_MESH] = "Exact - All polygons";
SHAPE_TYPES[SHAPE_TYPE_BOX] = "Box";
SHAPE_TYPES[SHAPE_TYPE_SPHERE] = "Sphere";
var SHAPE_TYPE_DEFAULT = SHAPE_TYPE_SIMPLE_COMPOUND;
var DYNAMIC_DEFAULT = false;
var prompt = desktop.customInputDialog({
@ -348,14 +349,14 @@ Windows.ScrollingWindow {
}
function deleteFile(index) {
var paths = [];
if (!index) {
for (var i = 0; i < selectedItemCount; ++i) {
index = treeView.selection.selectedIndexes[i];
paths[i] = assetProxyModel.data(index, 0x100);
}
}
if (!paths) {
return;
}
@ -364,13 +365,13 @@ Windows.ScrollingWindow {
var items = selectedItemCount.toString();
var isFolder = assetProxyModel.data(treeView.selection.currentIndex, 0x101);
var typeString = isFolder ? 'folder' : 'file';
if (selectedItemCount > 1) {
modalMessage = "You are about to delete " + items + " items \nDo you want to continue?";
} else {
modalMessage = "You are about to delete the following " + typeString + ":\n" + paths + "\nDo you want to continue?";
}
var object = desktop.messageBox({
icon: hifi.icons.question,
buttons: OriginalDialogs.StandardButton.Yes + OriginalDialogs.StandardButton.No,
@ -475,11 +476,11 @@ Windows.ScrollingWindow {
});
}
}
Item {
width: pane.contentWidth
height: pane.height
// The letterbox used for popup messages
LetterboxMessage {
id: letterboxMessage;
@ -541,7 +542,7 @@ Windows.ScrollingWindow {
anchors.margins: hifi.dimensions.contentMargin.x + 2 // Extra for border
anchors.left: parent.left
anchors.right: parent.right
treeModel: assetProxyModel
selectionMode: SelectionMode.ExtendedSelection
headerVisible: true
@ -561,9 +562,13 @@ Windows.ScrollingWindow {
id: bakedColumn
title: "Use Baked?"
role: "baked"
width: 100
width: 170
}
onSortIndicatorOrderChanged: {
Assets.sortProxyModel(sortIndicatorColumn, sortIndicatorOrder);
}
itemDelegate: Loader {
id: itemDelegateLoader
@ -599,7 +604,7 @@ Windows.ScrollingWindow {
}
sourceComponent: getComponent()
Component {
id: labelComponent
FiraSansSemiBold {
@ -608,15 +613,15 @@ Windows.ScrollingWindow {
color: colorScheme == hifi.colorSchemes.light
? (styleData.selected ? hifi.colors.black : hifi.colors.baseGrayHighlight)
: (styleData.selected ? hifi.colors.black : hifi.colors.lightGrayText)
horizontalAlignment: styleData.column === 1 ? TextInput.AlignHCenter : TextInput.AlignLeft
elide: Text.ElideMiddle
MouseArea {
id: mouseArea
anchors.fill: parent
acceptedButtons: Qt.NoButton
hoverEnabled: true
@ -638,7 +643,7 @@ Windows.ScrollingWindow {
color: colorScheme == hifi.colorSchemes.light
? (styleData.selected ? hifi.colors.black : hifi.colors.baseGrayHighlight)
: (styleData.selected ? hifi.colors.black : hifi.colors.lightGrayText)
elide: Text.ElideRight
horizontalAlignment: TextInput.AlignHCenter
@ -725,7 +730,7 @@ Windows.ScrollingWindow {
size: hifi.fontSizes.tableText
color: colorScheme == hifi.colorSchemes.light ? hifi.colors.black : hifi.colors.lightGrayText
}
Timer {
id: showTimer
interval: 1000
@ -744,7 +749,7 @@ Windows.ScrollingWindow {
treeLabelToolTip.visible = false;
}
}// End_OF( treeLabelToolTip )
MouseArea {
propagateComposedEvents: true
anchors.fill: parent
@ -802,7 +807,7 @@ Windows.ScrollingWindow {
anchors.left: treeView.left
anchors.right: treeView.right
anchors.bottom: uploadSection.top
RalewayRegular {
anchors.verticalCenter: parent.verticalCenter
@ -846,7 +851,7 @@ Windows.ScrollingWindow {
checked = Qt.binding(isChecked);
}
function isEnabled() {
if (!treeView.selection.hasSelection) {
return false;
@ -870,7 +875,7 @@ Windows.ScrollingWindow {
}
}
return true;
return true;
}
function isChecked() {
if (!treeView.selection.hasSelection) {
@ -878,10 +883,10 @@ Windows.ScrollingWindow {
}
var status = assetProxyModel.data(treeView.selection.currentIndex, 0x105);
return isEnabled() && status !== "Not Baked";
}
return isEnabled() && status !== "Not Baked";
}
}
Item {
anchors.verticalCenter: parent.verticalCenter
width: infoGlyph.size;
@ -905,7 +910,7 @@ Windows.ScrollingWindow {
"What is baking?",
"Baking compresses and optimizes files for faster network transfer and display. We recommend you bake your content to reduce initial load times for your visitors.");
}
}
}
}// End_OF( infoRow )
HifiControls.ContentSection {

View file

@ -1160,14 +1160,14 @@ Rectangle {
function authSuccessStep() {
if (!root.debugCheckoutSuccess) {
root.activeView = "checkoutMain";
} else {
root.activeView = "checkoutSuccess";
root.ownershipStatusReceived = false;
Commerce.alreadyOwned(root.itemId);
root.availableUpdatesReceived = false;
Commerce.getAvailableUpdates(root.itemId);
root.balanceReceived = false;
Commerce.balance();
} else {
root.activeView = "checkoutSuccess";
}
}

View file

@ -25,6 +25,7 @@ ScrollingWindow {
resizable: true
destroyOnHidden: false
implicitWidth: 424
opacity: parent.opacity
implicitHeight: isHMD ? 695 : 728
minSize: Qt.vector2d(424, 300)

View file

@ -58,7 +58,7 @@ Rectangle {
Component.onDestruction: {
assetMappingsModel.autoRefreshEnabled = false;
}
function letterbox(headerGlyph, headerText, message) {
letterboxMessage.headerGlyph = headerGlyph;
letterboxMessage.headerText = headerText;
@ -66,7 +66,7 @@ Rectangle {
letterboxMessage.visible = true;
letterboxMessage.popupRadius = 0;
}
function errorMessageBox(message) {
return tabletRoot.messageBox({
icon: hifi.icons.warning,
@ -145,7 +145,7 @@ Rectangle {
function canAddToWorld(path) {
var supportedExtensions = [/\.fbx\b/i, /\.obj\b/i, /\.jpg\b/i, /\.png\b/i];
if (selectedItemCount > 1) {
return false;
}
@ -154,8 +154,8 @@ Rectangle {
return total | new RegExp(current).test(path);
}, false);
}
function canRename() {
function canRename() {
if (treeView.selection.hasSelection && selectedItemCount == 1) {
return true;
} else {
@ -199,7 +199,7 @@ Rectangle {
var SHAPE_TYPE_STATIC_MESH = 3;
var SHAPE_TYPE_BOX = 4;
var SHAPE_TYPE_SPHERE = 5;
var SHAPE_TYPES = [];
SHAPE_TYPES[SHAPE_TYPE_NONE] = "No Collision";
SHAPE_TYPES[SHAPE_TYPE_SIMPLE_HULL] = "Basic - Whole model";
@ -207,7 +207,7 @@ Rectangle {
SHAPE_TYPES[SHAPE_TYPE_STATIC_MESH] = "Exact - All polygons";
SHAPE_TYPES[SHAPE_TYPE_BOX] = "Box";
SHAPE_TYPES[SHAPE_TYPE_SPHERE] = "Sphere";
var SHAPE_TYPE_DEFAULT = SHAPE_TYPE_SIMPLE_COMPOUND;
var DYNAMIC_DEFAULT = false;
var prompt = tabletRoot.customInputDialog({
@ -349,14 +349,14 @@ Rectangle {
}
function deleteFile(index) {
var paths = [];
if (!index) {
for (var i = 0; i < selectedItemCount; ++i) {
index = treeView.selection.selectedIndexes[i];
paths[i] = assetProxyModel.data(index, 0x100);
}
}
if (!paths) {
return;
}
@ -365,7 +365,7 @@ Rectangle {
var items = selectedItemCount.toString();
var isFolder = assetProxyModel.data(treeView.selection.currentIndex, 0x101);
var typeString = isFolder ? 'folder' : 'file';
if (selectedItemCount > 1) {
modalMessage = "You are about to delete " + items + " items \nDo you want to continue?";
} else {
@ -476,7 +476,7 @@ Rectangle {
});
}
}
// The letterbox used for popup messages
LetterboxMessage {
id: letterboxMessage;
@ -540,7 +540,7 @@ Rectangle {
anchors.margins: hifi.dimensions.contentMargin.x + 2 // Extra for border
anchors.left: parent.left
anchors.right: parent.right
treeModel: assetProxyModel
selectionMode: SelectionMode.ExtendedSelection
headerVisible: true
@ -560,9 +560,13 @@ Rectangle {
id: bakedColumn
title: "Use Baked?"
role: "baked"
width: 100
width: 170
}
onSortIndicatorOrderChanged: {
Assets.sortProxyModel(sortIndicatorColumn, sortIndicatorOrder);
}
itemDelegate: Loader {
id: itemDelegateLoader
@ -598,7 +602,7 @@ Rectangle {
}
sourceComponent: getComponent()
Component {
id: labelComponent
FiraSansSemiBold {
@ -607,15 +611,15 @@ Rectangle {
color: colorScheme == hifi.colorSchemes.light
? (styleData.selected ? hifi.colors.black : hifi.colors.baseGrayHighlight)
: (styleData.selected ? hifi.colors.black : hifi.colors.lightGrayText)
horizontalAlignment: styleData.column === 1 ? TextInput.AlignHCenter : TextInput.AlignLeft
elide: Text.ElideMiddle
MouseArea {
id: mouseArea
anchors.fill: parent
acceptedButtons: Qt.NoButton
hoverEnabled: true
@ -637,7 +641,7 @@ Rectangle {
color: colorScheme == hifi.colorSchemes.light
? (styleData.selected ? hifi.colors.black : hifi.colors.baseGrayHighlight)
: (styleData.selected ? hifi.colors.black : hifi.colors.lightGrayText)
elide: Text.ElideRight
horizontalAlignment: TextInput.AlignHCenter
@ -724,7 +728,7 @@ Rectangle {
size: hifi.fontSizes.tableText
color: colorScheme == hifi.colorSchemes.light ? hifi.colors.black : hifi.colors.lightGrayText
}
Timer {
id: showTimer
interval: 1000
@ -743,7 +747,7 @@ Rectangle {
treeLabelToolTip.visible = false;
}
}// End_OF( treeLabelToolTip )
MouseArea {
propagateComposedEvents: true
anchors.fill: parent
@ -801,7 +805,7 @@ Rectangle {
anchors.left: treeView.left
anchors.right: treeView.right
anchors.bottomMargin: hifi.dimensions.contentSpacing.y
RalewayRegular {
anchors.verticalCenter: parent.verticalCenter
@ -845,7 +849,7 @@ Rectangle {
checked = Qt.binding(isChecked);
}
function isEnabled() {
if (!treeView.selection.hasSelection) {
return false;
@ -869,7 +873,7 @@ Rectangle {
}
}
return true;
return true;
}
function isChecked() {
if (!treeView.selection.hasSelection) {
@ -877,10 +881,10 @@ Rectangle {
}
var status = assetProxyModel.data(treeView.selection.currentIndex, 0x105);
return isEnabled() && status !== "Not Baked";
}
return isEnabled() && status !== "Not Baked";
}
}
Item {
anchors.verticalCenter: parent.verticalCenter
width: infoGlyph.size;
@ -904,7 +908,7 @@ Rectangle {
"What is baking?",
"Baking compresses and optimizes files for faster network transfer and display. We recommend you bake your content to reduce initial load times for your visitors.");
}
}
}
}// End_OF( infoRow )
HifiControls.TabletContentSection {

View file

@ -71,6 +71,14 @@ Rectangle {
onAccepted: {
newModelDialog.keyboardEnabled = false;
}
onTextChanged : {
if (modelURL.text.length === 0){
button1.enabled = false;
} else {
button1.enabled = true;
}
}
MouseArea {
anchors.fill: parent
@ -200,6 +208,7 @@ Rectangle {
id: button1
text: qsTr("Add")
z: -1
enabled: false
onClicked: {
newModelDialog.sendToScript({
method: "newModelDialogAdd",

View file

@ -113,7 +113,6 @@ StackView {
id: addressBarDialog
property bool keyboardEnabled: false
property bool keyboardRaised: false
property bool punctuationMode: false
width: parent.width
@ -401,11 +400,10 @@ StackView {
addressLine.text = "";
}
}
HifiControls.Keyboard {
id: keyboard
raised: parent.keyboardEnabled && parent.keyboardRaised
raised: parent.keyboardEnabled
numeric: parent.punctuationMode
anchors {
bottom: parent.bottom
@ -413,7 +411,7 @@ StackView {
right: parent.right
}
}
}
function updateLocationText(enteringAddress) {

View file

@ -0,0 +1,18 @@
{
"Entities": [
{
"type": "Box",
"dimensions": {
"x": 20,
"y": 1,
"z": 20
},
"position" : {
"x": 0,
"y": -12,
"z": 0
}
}
],
"Version": 84
}

View file

@ -353,7 +353,7 @@ static const QString WEB_VIEW_TAG = "noDownload=true";
static const QString ZIP_EXTENSION = ".zip";
static const QString CONTENT_ZIP_EXTENSION = ".content.zip";
static const float MIRROR_FULLSCREEN_DISTANCE = 0.389f;
static const float MIRROR_FULLSCREEN_DISTANCE = 0.789f;
static const quint64 TOO_LONG_SINCE_LAST_SEND_DOWNSTREAM_AUDIO_STATS = 1 * USECS_PER_SECOND;
@ -941,7 +941,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
_constrainToolbarPosition("toolbar/constrainToolbarToCenterX", true),
_preferredCursor("preferredCursor", DEFAULT_CURSOR_NAME),
_scaleMirror(1.0f),
_rotateMirror(0.0f),
_mirrorYawOffset(0.0f),
_raiseMirror(0.0f),
_enableProcessOctreeThread(true),
_lastNackTime(usecTimestampNow()),
@ -959,8 +959,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
setProperty(hifi::properties::STEAM, (steamClient && steamClient->isRunning()));
setProperty(hifi::properties::CRASHED, _previousSessionCrashed);
_entityClipboard->setIsServerlessMode(true);
{
const QString TEST_SCRIPT = "--testScript";
const QString TRACE_FILE = "--traceFile";
@ -2813,8 +2811,9 @@ void Application::updateCamera(RenderArgs& renderArgs, float deltaTime) {
}
else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
_thirdPersonHMDCameraBoomValid= false;
if (isHMDMode()) {
auto mirrorBodyOrientation = myAvatar->getWorldOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f));
auto mirrorBodyOrientation = myAvatar->getWorldOrientation() * glm::quat(glm::vec3(0.0f, PI + _mirrorYawOffset, 0.0f));
glm::quat hmdRotation = extractRotation(myAvatar->getHMDSensorMatrix());
// Mirror HMD yaw and roll
@ -2837,12 +2836,15 @@ void Application::updateCamera(RenderArgs& renderArgs, float deltaTime) {
+ mirrorBodyOrientation * hmdOffset);
}
else {
_myCamera.setOrientation(myAvatar->getWorldOrientation()
* glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)));
auto userInputMapper = DependencyManager::get<UserInputMapper>();
const float YAW_SPEED = TWO_PI / 5.0f;
float deltaYaw = userInputMapper->getActionState(controller::Action::YAW) * YAW_SPEED * deltaTime;
_mirrorYawOffset += deltaYaw;
_myCamera.setOrientation(myAvatar->getWorldOrientation() * glm::quat(glm::vec3(0.0f, PI + _mirrorYawOffset, 0.0f)));
_myCamera.setPosition(myAvatar->getDefaultEyePosition()
+ glm::vec3(0, _raiseMirror * myAvatar->getModelScale(), 0)
+ (myAvatar->getWorldOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) *
glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror);
+ (myAvatar->getWorldOrientation() * glm::quat(glm::vec3(0.0f, _mirrorYawOffset, 0.0f))) *
glm::vec3(0.0f, 0.0f, -1.0f) * myAvatar->getBoomLength() * _scaleMirror);
}
renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE;
}
@ -3403,8 +3405,6 @@ void Application::keyPressEvent(QKeyEvent* event) {
} else {
setFullscreen(nullptr);
}
} else {
Menu::getInstance()->triggerOption(MenuOption::AddressBar);
}
break;
@ -3466,13 +3466,6 @@ void Application::keyPressEvent(QKeyEvent* event) {
}
break;
case Qt::Key_F: {
if (isOption) {
_physicsEngine->dumpNextStats();
}
break;
}
case Qt::Key_Asterisk:
Menu::getInstance()->triggerOption(MenuOption::DefaultSkybox);
break;
@ -3492,22 +3485,25 @@ void Application::keyPressEvent(QKeyEvent* event) {
case Qt::Key_S:
if (isShifted && isMeta && !isOption) {
Menu::getInstance()->triggerOption(MenuOption::SuppressShortTimings);
} else if (!isOption && !isShifted && isMeta) {
AudioInjectorOptions options;
options.localOnly = true;
options.stereo = true;
if (_snapshotSoundInjector) {
_snapshotSoundInjector->setOptions(options);
_snapshotSoundInjector->restart();
} else {
QByteArray samples = _snapshotSound->getByteArray();
_snapshotSoundInjector = AudioInjector::playSound(samples, options);
}
takeSnapshot(true);
}
break;
case Qt::Key_P: {
AudioInjectorOptions options;
options.localOnly = true;
options.stereo = true;
if (_snapshotSoundInjector) {
_snapshotSoundInjector->setOptions(options);
_snapshotSoundInjector->restart();
} else {
QByteArray samples = _snapshotSound->getByteArray();
_snapshotSoundInjector = AudioInjector::playSound(samples, options);
}
takeSnapshot(true);
break;
}
case Qt::Key_Apostrophe: {
if (isMeta) {
auto cursor = Cursor::Manager::instance().getCursor();
@ -3531,38 +3527,6 @@ void Application::keyPressEvent(QKeyEvent* event) {
Menu::getInstance()->triggerOption(MenuOption::Chat);
break;
case Qt::Key_Up:
if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
if (!isShifted) {
_scaleMirror *= 0.95f;
} else {
_raiseMirror += 0.05f;
}
}
break;
case Qt::Key_Down:
if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
if (!isShifted) {
_scaleMirror *= 1.05f;
} else {
_raiseMirror -= 0.05f;
}
}
break;
case Qt::Key_Left:
if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
_rotateMirror += PI / 20.0f;
}
break;
case Qt::Key_Right:
if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
_rotateMirror -= PI / 20.0f;
}
break;
#if 0
case Qt::Key_I:
if (isShifted) {
@ -4932,8 +4896,10 @@ void Application::cameraMenuChanged() {
auto menu = Menu::getInstance();
if (menu->isOptionChecked(MenuOption::FullscreenMirror)) {
if (!isHMDMode() && _myCamera.getMode() != CAMERA_MODE_MIRROR) {
_mirrorYawOffset = 0.0f;
_myCamera.setMode(CAMERA_MODE_MIRROR);
getMyAvatar()->reset(false, false, false); // to reset any active MyAvatar::FollowHelpers
getMyAvatar()->setBoomLength(MyAvatar::ZOOM_DEFAULT);
}
} else if (menu->isOptionChecked(MenuOption::FirstPerson)) {
if (_myCamera.getMode() != CAMERA_MODE_FIRST_PERSON) {
@ -5213,7 +5179,7 @@ void Application::update(float deltaTime) {
// FIXME can we drop drive keys and just have the avatar read the action states directly?
myAvatar->clearDriveKeys();
if (_myCamera.getMode() != CAMERA_MODE_INDEPENDENT) {
if (!_controllerScriptingInterface->areActionsCaptured()) {
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_Y, userInputMapper->getActionState(controller::Action::TRANSLATE_Y));
myAvatar->setDriveKey(MyAvatar::TRANSLATE_X, userInputMapper->getActionState(controller::Action::TRANSLATE_X));
@ -5226,6 +5192,7 @@ void Application::update(float deltaTime) {
myAvatar->setDriveKey(MyAvatar::ZOOM, userInputMapper->getActionState(controller::Action::TRANSLATE_CAMERA_Z));
}
myAvatar->setSprintMode((bool)userInputMapper->getActionState(controller::Action::SPRINT));
static const std::vector<controller::Action> avatarControllerActions = {
controller::Action::LEFT_HAND,
controller::Action::RIGHT_HAND,
@ -7491,7 +7458,7 @@ DisplayPluginPointer Application::getActiveDisplayPlugin() const {
return _displayPlugin;
}
if (!_displayPlugin) {
if (!_aboutToQuit && !_displayPlugin) {
const_cast<Application*>(this)->updateDisplayMode();
Q_ASSERT(_displayPlugin);
}

View file

@ -575,7 +575,7 @@ private:
Setting::Handle<QString> _preferredCursor;
float _scaleMirror;
float _rotateMirror;
float _mirrorYawOffset;
float _raiseMirror;
QSet<int> _keysPressed;

View file

@ -229,21 +229,21 @@ Menu::Menu() {
// View > First Person
auto firstPersonAction = cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash(
viewMenu, MenuOption::FirstPerson, Qt::CTRL | Qt::Key_F,
viewMenu, MenuOption::FirstPerson, Qt::Key_1,
true, qApp, SLOT(cameraMenuChanged())));
firstPersonAction->setProperty(EXCLUSION_GROUP_KEY, QVariant::fromValue(cameraModeGroup));
// View > Third Person
auto thirdPersonAction = cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash(
viewMenu, MenuOption::ThirdPerson, Qt::CTRL | Qt::Key_G,
viewMenu, MenuOption::ThirdPerson, Qt::Key_3,
false, qApp, SLOT(cameraMenuChanged())));
thirdPersonAction->setProperty(EXCLUSION_GROUP_KEY, QVariant::fromValue(cameraModeGroup));
// View > Mirror
auto viewMirrorAction = cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash(
viewMenu, MenuOption::FullscreenMirror, Qt::CTRL | Qt::Key_H,
viewMenu, MenuOption::FullscreenMirror, Qt::Key_2,
false, qApp, SLOT(cameraMenuChanged())));
viewMirrorAction->setProperty(EXCLUSION_GROUP_KEY, QVariant::fromValue(cameraModeGroup));

View file

@ -2186,7 +2186,6 @@ void MyAvatar::updateActionMotor(float deltaTime) {
glm::vec3 direction = forward + right;
if (state == CharacterController::State::Hover ||
_characterController.computeCollisionGroup() == BULLET_COLLISION_GROUP_COLLISIONLESS) {
// we can fly --> support vertical motion
glm::vec3 up = (getDriveKey(TRANSLATE_Y)) * IDENTITY_UP;
direction += up;
}
@ -2204,10 +2203,11 @@ void MyAvatar::updateActionMotor(float deltaTime) {
if (state == CharacterController::State::Hover) {
// we're flying --> complex acceleration curve that builds on top of current motor speed and caps at some max speed
float motorSpeed = glm::length(_actionMotorVelocity);
float finalMaxMotorSpeed = getSensorToWorldScale() * DEFAULT_AVATAR_MAX_FLYING_SPEED;
float finalMaxMotorSpeed = getSensorToWorldScale() * DEFAULT_AVATAR_MAX_FLYING_SPEED * _walkSpeedScalar;
float speedGrowthTimescale = 2.0f;
float speedIncreaseFactor = 1.8f;
float speedIncreaseFactor = 1.8f * _walkSpeedScalar;
motorSpeed *= 1.0f + glm::clamp(deltaTime / speedGrowthTimescale, 0.0f, 1.0f) * speedIncreaseFactor;
const float maxBoostSpeed = getSensorToWorldScale() * MAX_BOOST_SPEED;
@ -2223,7 +2223,7 @@ void MyAvatar::updateActionMotor(float deltaTime) {
_actionMotorVelocity = motorSpeed * direction;
} else {
// we're interacting with a floor --> simple horizontal speed and exponential decay
_actionMotorVelocity = getSensorToWorldScale() * _walkSpeed.get() * direction;
_actionMotorVelocity = getSensorToWorldScale() * (_walkSpeed.get() * _walkSpeedScalar) * direction;
}
float boomChange = getDriveKey(ZOOM);
@ -2816,7 +2816,11 @@ float MyAvatar::getUserEyeHeight() const {
}
float MyAvatar::getWalkSpeed() const {
return _walkSpeed.get();
return _walkSpeed.get() * _walkSpeedScalar;
}
void MyAvatar::setSprintMode(bool sprint) {
_walkSpeedScalar = sprint ? AVATAR_SPRINT_SPEED_SCALAR : AVATAR_WALK_SPEED_SCALAR;
}
void MyAvatar::setWalkSpeed(float value) {

View file

@ -395,6 +395,7 @@ public:
// Set what driving keys are being pressed to control thrust levels
void clearDriveKeys();
void setDriveKey(DriveKeys key, float val);
void setSprintMode(bool sprint);
float getDriveKey(DriveKeys key) const;
Q_INVOKABLE float getRawDriveKey(DriveKeys key) const;
void relayDriveKeysToCharacterController();
@ -836,7 +837,8 @@ private:
std::map<controller::Action, controller::Pose> _controllerPoseMap;
mutable std::mutex _controllerPoseMapMutex;
bool _hmdLeanRecenterEnabled = true;
bool _hmdLeanRecenterEnabled { true };
bool _sprint { false };
AnimPose _prePhysicsRoomPose;
std::mutex _holdActionsMutex;
std::vector<AvatarActionHold*> _holdActions;
@ -866,6 +868,7 @@ private:
// max unscaled forward movement speed
ThreadSafeValueCache<float> _walkSpeed { DEFAULT_AVATAR_MAX_WALKING_SPEED };
float _walkSpeedScalar { AVATAR_WALK_SPEED_SCALAR };
};
QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode);

View file

@ -152,6 +152,10 @@ void AssetMappingsScriptingInterface::deleteMappings(QStringList paths, QJSValue
request->start();
}
void AssetMappingsScriptingInterface::sortProxyModel(int column, Qt::SortOrder order) {
_proxyModel.sort(column, order);
}
void AssetMappingsScriptingInterface::getAllMappings(QJSValue callback) {
auto assetClient = DependencyManager::get<AssetClient>();
auto request = assetClient->createGetAllMappingsRequest();
@ -287,7 +291,7 @@ void AssetMappingModel::refresh() {
item->setData(parts[i], Qt::UserRole + 2);
item->setData("atp:" + fullPath, Qt::UserRole + 3);
item->setData(fullPath, Qt::UserRole + 4);
if (lastItem) {
lastItem->appendRow(item);
} else {

View file

@ -82,6 +82,7 @@ public:
Q_INVOKABLE void getAllMappings(QJSValue callback = QJSValue());
Q_INVOKABLE void renameMapping(QString oldPath, QString newPath, QJSValue callback = QJSValue());
Q_INVOKABLE void setBakingEnabled(QStringList paths, bool enabled, QJSValue callback = QJSValue());
Q_INVOKABLE void sortProxyModel(int column, Qt::SortOrder order = Qt::AscendingOrder);
protected:
QSet<AssetRequest*> _pendingRequests;

View file

@ -10,6 +10,7 @@
//
#include <map>
#include <algorithm>
#include <shared/QtHelpers.h>
#include <plugins/DisplayPlugin.h>
@ -182,7 +183,6 @@ void AudioDeviceList::resetDevice(bool contextIsHMD) {
}
void AudioDeviceList::onDeviceChanged(const QAudioDeviceInfo& device, bool isHMD) {
auto oldDevice = isHMD ? _selectedHMDDevice : _selectedDesktopDevice;
QAudioDeviceInfo& selectedDevice = isHMD ? _selectedHMDDevice : _selectedDesktopDevice;
selectedDevice = device;
@ -200,32 +200,137 @@ void AudioDeviceList::onDeviceChanged(const QAudioDeviceInfo& device, bool isHMD
emit dataChanged(createIndex(0, 0), createIndex(rowCount() - 1, 0));
}
void AudioDeviceList::onDevicesChanged(const QList<QAudioDeviceInfo>& devices, bool isHMD) {
QAudioDeviceInfo& selectedDevice = isHMD ? _selectedHMDDevice : _selectedDesktopDevice;
// Function returns 'strings similarity' as a number. The lesser number - the more similar strings are. Absolutely equal strings should return 0.
// Optimized version kindly provided by Ken
int levenshteinDistance(const QString& s1, const QString& s2) {
const int m = s1.size();
const int n = s2.size();
const QString& savedDeviceName = isHMD ? _hmdSavedDeviceName : _desktopSavedDeviceName;
if (m == 0) {
return n;
}
if (n == 0) {
return m;
}
auto cost = (int*)alloca((n + 1) * sizeof(int));
for (int j = 0; j <= n; j++) {
cost[j] = j;
}
for (int i = 0; i < m; i++) {
int prev = i;
cost[0] = i + 1;
for (int j = 0; j < n; j++) {
int temp = cost[j + 1];
cost[j + 1] = (s1[i] == s2[j]) ? prev : std::min(cost[j], std::min(temp, prev)) + 1;
prev = temp;
}
}
return cost[n];
}
std::shared_ptr<scripting::AudioDevice> getSimilarDevice(const QString& deviceName, const QList<std::shared_ptr<scripting::AudioDevice>>& devices) {
int minDistance = INT_MAX;
int minDistanceIndex = 0;
for (auto i = 0; i < devices.length(); ++i) {
auto distance = levenshteinDistance(deviceName, devices[i]->info.deviceName());
if (distance < minDistance) {
minDistance = distance;
minDistanceIndex = i;
}
}
return devices[minDistanceIndex];
}
void AudioDeviceList::onDevicesChanged(const QList<QAudioDeviceInfo>& devices) {
beginResetModel();
_devices.clear();
QList<std::shared_ptr<AudioDevice>> newDevices;
bool hmdIsSelected = false;
bool desktopIsSelected = false;
foreach(const QAudioDeviceInfo& deviceInfo, devices) {
for (bool isHMD : {false, true}) {
auto &backupSelectedDeviceName = isHMD ? _backupSelectedHMDDeviceName : _backupSelectedDesktopDeviceName;
if (deviceInfo.deviceName() == backupSelectedDeviceName) {
QAudioDeviceInfo& selectedDevice = isHMD ? _selectedHMDDevice : _selectedDesktopDevice;
selectedDevice = deviceInfo;
backupSelectedDeviceName.clear();
}
}
}
foreach(const QAudioDeviceInfo& deviceInfo, devices) {
AudioDevice device;
bool &isSelected = isHMD ? device.selectedHMD : device.selectedDesktop;
device.info = deviceInfo;
device.display = device.info.deviceName()
.replace("High Definition", "HD")
.remove("Device")
.replace(" )", ")");
if (!selectedDevice.isNull()) {
isSelected = (device.info == selectedDevice);
} else {
//no selected device for context. fallback to saved
isSelected = (device.info.deviceName() == savedDeviceName);
for (bool isHMD : {false, true}) {
QAudioDeviceInfo& selectedDevice = isHMD ? _selectedHMDDevice : _selectedDesktopDevice;
bool &isSelected = isHMD ? device.selectedHMD : device.selectedDesktop;
if (!selectedDevice.isNull()) {
isSelected = (device.info == selectedDevice);
}
else {
//no selected device for context. fallback to saved
const QString& savedDeviceName = isHMD ? _hmdSavedDeviceName : _desktopSavedDeviceName;
isSelected = (device.info.deviceName() == savedDeviceName);
}
if (isSelected) {
if (isHMD) {
hmdIsSelected = isSelected;
} else {
desktopIsSelected = isSelected;
}
// check if this device *is not* in old devices list - it means it was just re-plugged so needs to be selected explicitly
bool isNewDevice = true;
for (auto& oldDevice : _devices) {
if (oldDevice->info.deviceName() == device.info.deviceName()) {
isNewDevice = false;
break;
}
}
if (isNewDevice) {
emit selectedDevicePlugged(device.info, isHMD);
}
}
}
qDebug() << "adding audio device:" << device.display << device.selectedDesktop << device.selectedHMD << _mode;
_devices.push_back(newDevice(device));
newDevices.push_back(newDevice(device));
}
if (!newDevices.isEmpty()) {
if (!hmdIsSelected) {
_backupSelectedHMDDeviceName = !_selectedHMDDevice.isNull() ? _selectedHMDDevice.deviceName() : _hmdSavedDeviceName;
auto device = getSimilarDevice(_backupSelectedHMDDeviceName, newDevices);
device->selectedHMD = true;
emit selectedDevicePlugged(device->info, true);
}
if (!desktopIsSelected) {
_backupSelectedDesktopDeviceName = !_selectedDesktopDevice.isNull() ? _selectedDesktopDevice.deviceName() : _desktopSavedDeviceName;
auto device = getSimilarDevice(_backupSelectedDesktopDeviceName, newDevices);
device->selectedDesktop = true;
emit selectedDevicePlugged(device->info, false);
}
}
_devices.swap(newDevices);
endResetModel();
}
@ -271,12 +376,10 @@ AudioDevices::AudioDevices(bool& contextIsHMD) : _contextIsHMD(contextIsHMD) {
// connections are made after client is initialized, so we must also fetch the devices
const QList<QAudioDeviceInfo>& devicesInput = client->getAudioDevices(QAudio::AudioInput);
const QList<QAudioDeviceInfo>& devicesOutput = client->getAudioDevices(QAudio::AudioOutput);
//setup HMD devices
_inputs.onDevicesChanged(devicesInput, true);
_outputs.onDevicesChanged(devicesOutput, true);
//setup Desktop devices
_inputs.onDevicesChanged(devicesInput, false);
_outputs.onDevicesChanged(devicesOutput, false);
//setup devices
_inputs.onDevicesChanged(devicesInput);
_outputs.onDevicesChanged(devicesOutput);
}
AudioDevices::~AudioDevices() {}
@ -375,11 +478,19 @@ void AudioDevices::onDevicesChanged(QAudio::Mode mode, const QList<QAudioDeviceI
//set devices for both contexts
if (mode == QAudio::AudioInput) {
_inputs.onDevicesChanged(devices, _contextIsHMD);
_inputs.onDevicesChanged(devices, !_contextIsHMD);
_inputs.onDevicesChanged(devices);
static std::once_flag onceAfterInputDevicesChanged;
std::call_once(onceAfterInputDevicesChanged, [&] { // we only want 'selectedDevicePlugged' signal to be handled after initial list of input devices was populated
connect(&_inputs, &AudioDeviceList::selectedDevicePlugged, this, &AudioDevices::chooseInputDevice);
});
} else { // if (mode == QAudio::AudioOutput)
_outputs.onDevicesChanged(devices, _contextIsHMD);
_outputs.onDevicesChanged(devices, !_contextIsHMD);
_outputs.onDevicesChanged(devices);
static std::once_flag onceAfterOutputDevicesChanged;
std::call_once(onceAfterOutputDevicesChanged, [&] { // we only want 'selectedDevicePlugged' signal to be handled after initial list of output devices was populated
connect(&_outputs, &AudioDeviceList::selectedDevicePlugged, this, &AudioDevices::chooseOutputDevice);
});
}
}

View file

@ -51,10 +51,11 @@ public:
signals:
void deviceChanged(const QAudioDeviceInfo& device);
void selectedDevicePlugged(const QAudioDeviceInfo& device, bool isHMD);
protected slots:
void onDeviceChanged(const QAudioDeviceInfo& device, bool isHMD);
void onDevicesChanged(const QList<QAudioDeviceInfo>& devices, bool isHMD);
void onDevicesChanged(const QList<QAudioDeviceInfo>& devices);
protected:
friend class AudioDevices;
@ -64,6 +65,8 @@ protected:
const QAudio::Mode _mode;
QAudioDeviceInfo _selectedDesktopDevice;
QAudioDeviceInfo _selectedHMDDevice;
QString _backupSelectedDesktopDeviceName;
QString _backupSelectedHMDDeviceName;
QList<std::shared_ptr<AudioDevice>> _devices;
QString _hmdSavedDeviceName;
QString _desktopSavedDeviceName;
@ -117,13 +120,13 @@ public:
AudioDevices(bool& contextIsHMD);
virtual ~AudioDevices();
void chooseInputDevice(const QAudioDeviceInfo& device, bool isHMD);
void chooseOutputDevice(const QAudioDeviceInfo& device, bool isHMD);
signals:
void nop();
private slots:
void chooseInputDevice(const QAudioDeviceInfo& device, bool isHMD);
void chooseOutputDevice(const QAudioDeviceInfo& device, bool isHMD);
void onContextChanged(const QString& context);
void onDeviceSelected(QAudio::Mode mode, const QAudioDeviceInfo& device,
const QAudioDeviceInfo& previousDevice, bool isHMD);

View file

@ -78,13 +78,17 @@ void WindowScriptingInterface::setFocus() {
});
}
void WindowScriptingInterface::raiseMainWindow() {
void WindowScriptingInterface::raise() {
// It's forbidden to call raise() from another thread.
qApp->postLambdaEvent([] {
qApp->raise();
});
}
void WindowScriptingInterface::raiseMainWindow() {
raise();
}
/// Display an alert box
/// \param const QString& message message to display
/// \return QScriptValue::UndefinedValue

View file

@ -68,9 +68,16 @@ public slots:
*/
void setFocus();
/**jsdoc
* Raise the Interface window if it is minimized. If raised, the window gains focus.
* @function Window.raise
*/
void raise();
/**jsdoc
* Raise the Interface window if it is minimized. If raised, the window gains focus.
* @function Window.raiseMainWindow
* @deprecated Use {@link Window.raise|raise} instead.
*/
void raiseMainWindow();

View file

@ -54,6 +54,7 @@ Overlays::Overlays() {
}
void Overlays::cleanupAllOverlays() {
_shuttingDown = true;
QMap<OverlayID, Overlay::Pointer> overlaysHUD;
QMap<OverlayID, Overlay::Pointer> overlaysWorld;
{
@ -147,6 +148,10 @@ void Overlays::enable() {
// Note, can't be invoked by scripts, but can be called by the InterfaceParentFinder
// class on packet processing threads
Overlay::Pointer Overlays::getOverlay(OverlayID id) const {
if (_shuttingDown) {
return nullptr;
}
QMutexLocker locker(&_mutex);
if (_overlaysHUD.contains(id)) {
return _overlaysHUD[id];
@ -157,6 +162,10 @@ Overlay::Pointer Overlays::getOverlay(OverlayID id) const {
}
OverlayID Overlays::addOverlay(const QString& type, const QVariant& properties) {
if (_shuttingDown) {
return UNKNOWN_OVERLAY_ID;
}
if (QThread::currentThread() != thread()) {
OverlayID result;
PROFILE_RANGE(script, __FUNCTION__);
@ -261,6 +270,10 @@ OverlayID Overlays::addOverlay(const QString& type, const QVariant& properties)
}
OverlayID Overlays::addOverlay(const Overlay::Pointer& overlay) {
if (_shuttingDown) {
return UNKNOWN_OVERLAY_ID;
}
OverlayID thisID = OverlayID(QUuid::createUuid());
overlay->setOverlayID(thisID);
overlay->setStackOrder(_stackOrder++);
@ -283,6 +296,10 @@ OverlayID Overlays::addOverlay(const Overlay::Pointer& overlay) {
}
OverlayID Overlays::cloneOverlay(OverlayID id) {
if (_shuttingDown) {
return UNKNOWN_OVERLAY_ID;
}
if (QThread::currentThread() != thread()) {
OverlayID result;
PROFILE_RANGE(script, __FUNCTION__);
@ -301,6 +318,10 @@ OverlayID Overlays::cloneOverlay(OverlayID id) {
}
bool Overlays::editOverlay(OverlayID id, const QVariant& properties) {
if (_shuttingDown) {
return false;
}
auto thisOverlay = getOverlay(id);
if (!thisOverlay) {
return false;
@ -320,6 +341,10 @@ bool Overlays::editOverlay(OverlayID id, const QVariant& properties) {
}
bool Overlays::editOverlays(const QVariant& propertiesById) {
if (_shuttingDown) {
return false;
}
bool defer2DOverlays = QThread::currentThread() != thread();
QVariantMap deferrred;
@ -351,6 +376,10 @@ bool Overlays::editOverlays(const QVariant& propertiesById) {
}
void Overlays::deleteOverlay(OverlayID id) {
if (_shuttingDown) {
return;
}
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "deleteOverlay", Q_ARG(OverlayID, id));
return;
@ -374,6 +403,9 @@ void Overlays::deleteOverlay(OverlayID id) {
}
QString Overlays::getOverlayType(OverlayID overlayId) {
if (_shuttingDown) {
return "";
}
if (QThread::currentThread() != thread()) {
QString result;
PROFILE_RANGE(script, __FUNCTION__);
@ -388,8 +420,23 @@ QString Overlays::getOverlayType(OverlayID overlayId) {
return "";
}
QObject* Overlays::getOverlayObject(OverlayID id) {
if (QThread::currentThread() != thread()) {
QObject* result;
PROFILE_RANGE(script, __FUNCTION__);
BLOCKING_INVOKE_METHOD(this, "getOverlayObject", Q_RETURN_ARG(QObject*, result), Q_ARG(OverlayID, id));
return result;
}
Overlay::Pointer thisOverlay = getOverlay(id);
if (thisOverlay) {
return qobject_cast<QObject*>(&(*thisOverlay));
}
return nullptr;
}
OverlayID Overlays::getOverlayAtPoint(const glm::vec2& point) {
if (!_enabled) {
if (_shuttingDown || !_enabled) {
return UNKNOWN_OVERLAY_ID;
}

View file

@ -235,6 +235,50 @@ public slots:
*/
QString getOverlayType(OverlayID overlayId);
/**jsdoc
* Get the overlay script object. In particular, this is useful for accessing the event bridge for a <code>web3d</code>
* overlay.
* @function Overlays.getOverlayObject
* @param {Uuid} overlayID - The ID of the overlay to get the script object of.
* @returns {object} The script object for the overlay if found.
* @example <caption>Receive "hello" messages from a <code>web3d</code> overlay.</caption>
* // HTML file: name "web3d.html".
* <!DOCTYPE html>
* <html>
* <head>
* <title>HELLO</title>
* </head>
* <body>
* <h1>HELLO</h1></h1>
* <script>
* setInterval(function () {
* EventBridge.emitWebEvent("hello");
* }, 2000);
* </script>
* </body>
* </html>
*
* // Script file.
* var web3dOverlay = Overlays.addOverlay("web3d", {
* position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, {x: 0, y: 0.5, z: -3 })),
* rotation: MyAvatar.orientation,
* url: Script.resolvePath("web3d.html"),
* alpha: 1.0
* });
*
* function onWebEventReceived(event) {
* print("onWebEventReceived() : " + JSON.stringify(event));
* }
*
* overlayObject = Overlays.getOverlayObject(web3dOverlay);
* overlayObject.webEventReceived.connect(onWebEventReceived);
*
* Script.scriptEnding.connect(function () {
* Overlays.deleteOverlay(web3dOverlay);
* });
*/
QObject* getOverlayObject(OverlayID id);
/**jsdoc
* Get the ID of the 2D overlay at a particular point on the screen or HUD.
* @function Overlays.getOverlayAtPoint
@ -680,6 +724,7 @@ private:
unsigned int _stackOrder { 1 };
bool _enabled = true;
std::atomic<bool> _shuttingDown{ false };
PointerEvent calculateOverlayPointerEvent(OverlayID overlayID, PickRay ray, RayToOverlayIntersectionResult rayPickResult,
QMouseEvent* event, PointerEvent::EventType eventType);

View file

@ -39,18 +39,20 @@ void QmlOverlay::buildQmlElement(const QUrl& url) {
auto offscreenUi = DependencyManager::get<OffscreenUi>();
offscreenUi->load(url, [=](QQmlContext* context, QObject* object) {
QQuickItem* rawPtr = dynamic_cast<QQuickItem*>(object);
// Create a shared ptr with a custom deleter lambda, that calls deleteLater
_qmlElement = std::shared_ptr<QQuickItem>(rawPtr, [](QQuickItem* ptr) {
if (ptr) {
ptr->deleteLater();
}
});
_qmlElement = dynamic_cast<QQuickItem*>(object);
connect(_qmlElement, &QObject::destroyed, this, &QmlOverlay::qmlElementDestroyed);
});
}
void QmlOverlay::qmlElementDestroyed() {
_qmlElement = nullptr;
}
QmlOverlay::~QmlOverlay() {
_qmlElement.reset();
if (_qmlElement) {
_qmlElement->deleteLater();
}
_qmlElement = nullptr;
}
// QmlOverlay replaces Overlay's properties with those defined in the QML file used but keeps Overlay2D's properties.
@ -62,15 +64,13 @@ void QmlOverlay::setProperties(const QVariantMap& properties) {
Overlay2D::setProperties(properties);
auto bounds = _bounds;
std::weak_ptr<QQuickItem> weakQmlElement = _qmlElement;
// check to see if qmlElement still exists
auto qmlElement = weakQmlElement.lock();
if (qmlElement) {
qmlElement->setX(bounds.left());
qmlElement->setY(bounds.top());
qmlElement->setWidth(bounds.width());
qmlElement->setHeight(bounds.height());
QMetaObject::invokeMethod(qmlElement.get(), "updatePropertiesFromScript", Qt::DirectConnection, Q_ARG(QVariant, properties));
if (_qmlElement) {
_qmlElement->setX(bounds.left());
_qmlElement->setY(bounds.top());
_qmlElement->setWidth(bounds.width());
_qmlElement->setHeight(bounds.height());
QMetaObject::invokeMethod(_qmlElement, "updatePropertiesFromScript", Qt::DirectConnection, Q_ARG(QVariant, properties));
}
}

View file

@ -32,10 +32,11 @@ public:
void render(RenderArgs* args) override;
private:
Q_INVOKABLE void qmlElementDestroyed();
Q_INVOKABLE void buildQmlElement(const QUrl& url);
protected:
std::shared_ptr<QQuickItem> _qmlElement;
QQuickItem* _qmlElement{ nullptr };
};
#endif // hifi_QmlOverlay_h

View file

@ -183,6 +183,7 @@ namespace controller {
makeButtonPair(Action::ACTION2, "ACTION2"),
makeButtonPair(Action::CONTEXT_MENU, "CONTEXT_MENU"),
makeButtonPair(Action::TOGGLE_MUTE, "TOGGLE_MUTE"),
makeButtonPair(Action::SPRINT, "SPRINT")
};
return availableInputs;
}

View file

@ -174,6 +174,7 @@ enum class Action {
TRACKED_OBJECT_13,
TRACKED_OBJECT_14,
TRACKED_OBJECT_15,
SPRINT,
NUM_ACTIONS
};

View file

@ -30,12 +30,7 @@
#include "UserActivityLogger.h"
#include "udt/PacketHeaders.h"
#if USE_STABLE_GLOBAL_SERVICES
const QString DEFAULT_HIFI_ADDRESS = "hifi://welcome/hello";
#else
const QString DEFAULT_HIFI_ADDRESS = "hifi://dev-welcome/hello";
#endif
const QString DEFAULT_HIFI_ADDRESS = "file:///~/serverless/tutorial.json";
const QString ADDRESS_MANAGER_SETTINGS_GROUP = "AddressManager";
const QString SETTINGS_CURRENT_ADDRESS_KEY = "address";

View file

@ -166,18 +166,30 @@ bool OffscreenSurface::eventFilter(QObject* originalDestination, QEvent* event)
case QEvent::TouchUpdate:
case QEvent::TouchEnd: {
QTouchEvent *originalEvent = static_cast<QTouchEvent *>(event);
QTouchEvent fakeEvent(*originalEvent);
auto newTouchPoints = fakeEvent.touchPoints();
for (size_t i = 0; i < newTouchPoints.size(); ++i) {
const auto &originalPoint = originalEvent->touchPoints()[i];
auto &newPoint = newTouchPoints[i];
newPoint.setPos(originalPoint.pos());
QEvent::Type fakeMouseEventType = QEvent::None;
Qt::MouseButton fakeMouseButton = Qt::LeftButton;
Qt::MouseButtons fakeMouseButtons = Qt::NoButton;
switch (event->type()) {
case QEvent::TouchBegin:
fakeMouseEventType = QEvent::MouseButtonPress;
fakeMouseButtons = Qt::LeftButton;
break;
case QEvent::TouchUpdate:
fakeMouseEventType = QEvent::MouseMove;
fakeMouseButtons = Qt::LeftButton;
break;
case QEvent::TouchEnd:
fakeMouseEventType = QEvent::MouseButtonRelease;
fakeMouseButtons = Qt::NoButton;
break;
}
fakeEvent.setTouchPoints(newTouchPoints);
if (QCoreApplication::sendEvent(_sharedObject->getWindow(), &fakeEvent)) {
qInfo() << __FUNCTION__ << "sent fake touch event:" << fakeEvent.type()
<< "_quickWindow handled it... accepted:" << fakeEvent.isAccepted();
return false; //event->isAccepted();
// Same case as OffscreenUi.cpp::eventFilter: touch events are always being accepted so we now use mouse events and consider one touch, touchPoints()[0].
QMouseEvent fakeMouseEvent(fakeMouseEventType, originalEvent->touchPoints()[0].pos(), fakeMouseButton, fakeMouseButtons, Qt::NoModifier);
fakeMouseEvent.ignore();
if (QCoreApplication::sendEvent(_sharedObject->getWindow(), &fakeMouseEvent)) {
/*qInfo() << __FUNCTION__ << "sent fake touch event:" << fakeMouseEvent.type()
<< "_quickWindow handled it... accepted:" << fakeMouseEvent.isAccepted();*/
return fakeMouseEvent.isAccepted();
}
break;
}

View file

@ -69,6 +69,7 @@ SharedObject::SharedObject() {
_quickWindow->setColor(QColor(255, 255, 255, 0));
_quickWindow->setClearBeforeRendering(true);
QObject::connect(qApp, &QCoreApplication::aboutToQuit, this, &SharedObject::onAboutToQuit);
}
@ -124,6 +125,7 @@ void SharedObject::setRootItem(QQuickItem* rootItem) {
_renderThread->setObjectName(objectName());
_renderThread->start();
// Create event handler for the render thread
_renderObject = new RenderEventHandler(this, _renderThread);
QCoreApplication::postEvent(this, new OffscreenEvent(OffscreenEvent::Initialize));
@ -152,9 +154,16 @@ void SharedObject::destroy() {
QObject::disconnect(_renderControl);
QObject::disconnect(qApp);
QMutexLocker lock(&_mutex);
_quit = true;
QCoreApplication::postEvent(_renderObject, new OffscreenEvent(OffscreenEvent::Quit));
{
QMutexLocker lock(&_mutex);
_quit = true;
QCoreApplication::postEvent(_renderObject, new OffscreenEvent(OffscreenEvent::Quit), Qt::HighEventPriority);
}
// Block until the rendering thread has stopped
// FIXME this is undesirable because this is blocking the main thread,
// but I haven't found a reliable way to do this only at application
// shutdown
_renderThread->wait();
}

View file

@ -118,9 +118,15 @@ uint32_t Item::fetchMetaSubItemBounds(ItemBounds& subItemBounds, Scene& scene) c
auto numSubs = fetchMetaSubItems(subItems);
for (auto id : subItems) {
auto& item = scene.getItem(id);
if (item.exist()) {
subItemBounds.emplace_back(id, item.getBound());
// TODO: Adding an extra check here even thought we shouldn't have too.
// We have cases when the id returned by fetchMetaSubItems is not allocated
if (scene.isAllocatedID(id)) {
auto& item = scene.getItem(id);
if (item.exist()) {
subItemBounds.emplace_back(id, item.getBound());
} else {
numSubs--;
}
} else {
numSubs--;
}

View file

@ -59,5 +59,7 @@ static const float MIN_AVATAR_SCALE = 0.005f;
static const float MAX_AVATAR_HEIGHT = 1000.0f * DEFAULT_AVATAR_HEIGHT; // meters
static const float MIN_AVATAR_HEIGHT = 0.005f * DEFAULT_AVATAR_HEIGHT; // meters
static const float AVATAR_WALK_SPEED_SCALAR = 1.0f;
static const float AVATAR_SPRINT_SPEED_SCALAR = 3.0f;
#endif // hifi_AvatarConstants_h

View file

@ -26,14 +26,14 @@ var RADIUS_RATE = 1.0 / 100.0;
var PAN_RATE = 250.0;
var Y_AXIS = {
x: 0,
y: 1,
z: 0
x: 0,
y: 1,
z: 0
};
var X_AXIS = {
x: 1,
y: 0,
z: 0
x: 1,
y: 0,
z: 0
};
var LOOK_AT_TIME = 500;
@ -56,21 +56,20 @@ var mode = noMode;
var mouseLastX = 0;
var mouseLastY = 0;
var center = {
x: 0,
y: 0,
z: 0
x: 0,
y: 0,
z: 0
};
var position = {
x: 0,
y: 0,
z: 0
x: 0,
y: 0,
z: 0
};
var vector = {
x: 0,
y: 0,
z: 0
x: 0,
y: 0,
z: 0
};
var radius = 0.0;
var azimuth = 0.0;
@ -83,258 +82,248 @@ var rotatingTowardsTarget = false;
var targetCamOrientation;
var oldPosition, oldOrientation;
function orientationOf(vector) {
var direction,
yaw,
pitch;
var direction,
yaw,
pitch;
direction = Vec3.normalize(vector);
yaw = Quat.angleAxis(Math.atan2(direction.x, direction.z) * RAD_TO_DEG, Y_AXIS);
pitch = Quat.angleAxis(Math.asin(-direction.y) * RAD_TO_DEG, X_AXIS);
return Quat.multiply(yaw, pitch);
direction = Vec3.normalize(vector);
yaw = Quat.angleAxis(Math.atan2(direction.x, direction.z) * RAD_TO_DEG, Y_AXIS);
pitch = Quat.angleAxis(Math.asin(-direction.y) * RAD_TO_DEG, X_AXIS);
return Quat.multiply(yaw, pitch);
}
function handleRadialMode(dx, dy) {
azimuth += dx / AZIMUTH_RATE;
radius += radius * dy * RADIUS_RATE;
if (radius < 1) {
radius = 1;
}
azimuth += dx / AZIMUTH_RATE;
radius += radius * dy * RADIUS_RATE;
if (radius < 1) {
radius = 1;
}
vector = {
x: (Math.cos(altitude) * Math.cos(azimuth)) * radius,
y: Math.sin(altitude) * radius,
z: (Math.cos(altitude) * Math.sin(azimuth)) * radius
};
position = Vec3.sum(center, vector);
Camera.setPosition(position);
Camera.setOrientation(orientationOf(vector));
vector = {
x: (Math.cos(altitude) * Math.cos(azimuth)) * radius,
y: Math.sin(altitude) * radius,
z: (Math.cos(altitude) * Math.sin(azimuth)) * radius
};
position = Vec3.sum(center, vector);
Camera.setPosition(position);
Camera.setOrientation(orientationOf(vector));
}
function handleOrbitMode(dx, dy) {
azimuth += dx / AZIMUTH_RATE;
altitude += dy / ALTITUDE_RATE;
if (altitude > PI / 2.0) {
altitude = PI / 2.0;
}
if (altitude < -PI / 2.0) {
altitude = -PI / 2.0;
}
azimuth += dx / AZIMUTH_RATE;
altitude += dy / ALTITUDE_RATE;
if (altitude > PI / 2.0) {
altitude = PI / 2.0;
}
if (altitude < -PI / 2.0) {
altitude = -PI / 2.0;
}
vector = {
x: (Math.cos(altitude) * Math.cos(azimuth)) * radius,
y: Math.sin(altitude) * radius,
z: (Math.cos(altitude) * Math.sin(azimuth)) * radius
};
position = Vec3.sum(center, vector);
Camera.setPosition(position);
Camera.setOrientation(orientationOf(vector));
vector = {
x: (Math.cos(altitude) * Math.cos(azimuth)) * radius,
y: Math.sin(altitude) * radius,
z: (Math.cos(altitude) * Math.sin(azimuth)) * radius
};
position = Vec3.sum(center, vector);
Camera.setPosition(position);
Camera.setOrientation(orientationOf(vector));
}
function handlePanMode(dx, dy) {
var up = Quat.getUp(Camera.getOrientation());
var right = Quat.getRight(Camera.getOrientation());
var distance = Vec3.length(vector);
var up = Quat.getUp(Camera.getOrientation());
var right = Quat.getRight(Camera.getOrientation());
var distance = Vec3.length(vector);
var dv = Vec3.sum(Vec3.multiply(up, distance * dy / PAN_RATE), Vec3.multiply(right, -distance * dx / PAN_RATE));
var dv = Vec3.sum(Vec3.multiply(up, distance * dy / PAN_RATE), Vec3.multiply(right, -distance * dx / PAN_RATE));
center = Vec3.sum(center, dv);
position = Vec3.sum(position, dv);
center = Vec3.sum(center, dv);
position = Vec3.sum(position, dv);
Camera.setPosition(position);
Camera.setOrientation(orientationOf(vector));
Camera.setPosition(position);
Camera.setOrientation(orientationOf(vector));
}
function saveCameraState() {
oldMode = Camera.mode;
oldPosition = Camera.getPosition();
oldOrientation = Camera.getOrientation();
oldMode = Camera.mode;
oldPosition = Camera.getPosition();
oldOrientation = Camera.getOrientation();
Camera.mode = "independent";
Camera.setPosition(oldPosition);
Camera.mode = "independent";
Camera.setPosition(oldPosition);
}
function restoreCameraState() {
Camera.mode = oldMode;
Camera.setPosition(oldPosition);
Camera.setOrientation(oldOrientation);
Camera.mode = oldMode;
Camera.setPosition(oldPosition);
Camera.setOrientation(oldOrientation);
}
function handleModes() {
var newMode = (mode == noMode) ? noMode : detachedMode;
if (alt) {
if (control) {
if (shift) {
newMode = panningMode;
} else {
newMode = orbitMode;
}
} else {
newMode = radialMode;
var newMode = (mode == noMode) ? noMode : detachedMode;
if (alt) {
if (control) {
if (shift) {
newMode = panningMode;
} else {
newMode = orbitMode;
}
} else {
newMode = radialMode;
}
}
}
// if entering detachMode
if (newMode == detachedMode && mode != detachedMode) {
avatarPosition = MyAvatar.position;
avatarOrientation = MyAvatar.orientation;
}
// if leaving detachMode
if (mode == detachedMode && newMode == detachedMode &&
(avatarPosition.x != MyAvatar.position.x ||
avatarPosition.y != MyAvatar.position.y ||
avatarPosition.z != MyAvatar.position.z ||
avatarOrientation.x != MyAvatar.orientation.x ||
avatarOrientation.y != MyAvatar.orientation.y ||
avatarOrientation.z != MyAvatar.orientation.z ||
avatarOrientation.w != MyAvatar.orientation.w)) {
newMode = noMode;
}
// if entering detachMode
if (newMode == detachedMode && mode != detachedMode) {
avatarPosition = MyAvatar.position;
avatarOrientation = MyAvatar.orientation;
}
// if leaving detachMode
if (mode == detachedMode && newMode == detachedMode &&
(avatarPosition.x != MyAvatar.position.x ||
avatarPosition.y != MyAvatar.position.y ||
avatarPosition.z != MyAvatar.position.z ||
avatarOrientation.x != MyAvatar.orientation.x ||
avatarOrientation.y != MyAvatar.orientation.y ||
avatarOrientation.z != MyAvatar.orientation.z ||
avatarOrientation.w != MyAvatar.orientation.w)) {
newMode = noMode;
}
if (mode == noMode && newMode != noMode && Camera.mode == "independent") {
newMode = noMode;
}
if (mode == noMode && newMode != noMode && Camera.mode == "independent") {
newMode = noMode;
}
// if leaving noMode
if (mode == noMode && newMode != noMode) {
saveCameraState();
}
// if entering noMode
if (newMode == noMode && mode != noMode) {
restoreCameraState();
}
// if leaving noMode
if (mode == noMode && newMode != noMode) {
saveCameraState();
}
// if entering noMode
if (newMode == noMode && mode != noMode) {
restoreCameraState();
}
mode = newMode;
mode = newMode;
}
function keyPressEvent(event) {
var changed = false;
var changed = false;
if (event.text == "ALT") {
alt = true;
changed = true;
}
if (event.text == "CONTROL") {
control = true;
changed = true;
}
if (event.text == "SHIFT") {
shift = true;
changed = true;
}
if (event.text == "ALT") {
alt = true;
changed = true;
}
if (event.text == "CONTROL") {
control = true;
changed = true;
}
if (event.text == "SHIFT") {
shift = true;
changed = true;
}
if (changed) {
handleModes();
}
if (changed) {
handleModes();
}
}
function keyReleaseEvent(event) {
var changed = false;
var changed = false;
if (event.text == "ALT") {
alt = false;
changed = true;
mode = noMode;
restoreCameraState();
}
if (event.text == "CONTROL") {
control = false;
changed = true;
}
if (event.text == "SHIFT") {
shift = false;
changed = true;
}
if (changed) {
handleModes();
}
}
function mousePressEvent(event) {
if (alt && !isActive) {
mouseLastX = event.x;
mouseLastY = event.y;
// Compute trajectories related values
var pickRay = Camera.computePickRay(mouseLastX, mouseLastY);
var modelIntersection = Entities.findRayIntersection(pickRay, true);
position = Camera.getPosition();
var avatarTarget = MyAvatar.getTargetAvatarPosition();
var distance = -1;
var string;
if (modelIntersection.intersects && modelIntersection.accurate) {
distance = modelIntersection.distance;
center = modelIntersection.intersection;
string = "Inspecting model";
//We've selected our target, now orbit towards it automatically
rotatingTowardsTarget = true;
//calculate our target cam rotation
Script.setTimeout(function() {
rotatingTowardsTarget = false;
}, LOOK_AT_TIME);
vector = Vec3.subtract(position, center);
targetCamOrientation = orientationOf(vector);
radius = Vec3.length(vector);
azimuth = Math.atan2(vector.z, vector.x);
altitude = Math.asin(vector.y / Vec3.length(vector));
isActive = true;
if (event.text == "ALT") {
alt = false;
changed = true;
mode = noMode;
restoreCameraState();
}
if (event.text == "CONTROL") {
control = false;
changed = true;
}
if (event.text == "SHIFT") {
shift = false;
changed = true;
}
}
if (changed) {
handleModes();
}
}
function mousePressEvent(event) {
if (alt && !isActive) {
mouseLastX = event.x;
mouseLastY = event.y;
// Compute trajectories related values
var pickRay = Camera.computePickRay(mouseLastX, mouseLastY);
var modelIntersection = Entities.findRayIntersection(pickRay, true);
var avatarIntersection = AvatarList.findRayIntersection(pickRay);
position = Camera.getPosition();
if (avatarIntersection.intersects || (modelIntersection.intersects && modelIntersection.accurate)) {
if (avatarIntersection.intersects) {
center = avatarIntersection.intersection;
} else {
center = modelIntersection.intersection;
}
// We've selected our target, now orbit towards it automatically
rotatingTowardsTarget = true;
// calculate our target cam rotation
Script.setTimeout(function () {
rotatingTowardsTarget = false;
}, LOOK_AT_TIME);
vector = Vec3.subtract(position, center);
targetCamOrientation = orientationOf(vector);
radius = Vec3.length(vector);
azimuth = Math.atan2(vector.z, vector.x);
altitude = Math.asin(vector.y / Vec3.length(vector));
isActive = true;
}
}
}
function mouseReleaseEvent(event) {
if (isActive) {
isActive = false;
}
if (isActive) {
isActive = false;
}
}
function mouseMoveEvent(event) {
if (isActive && mode != noMode && !rotatingTowardsTarget) {
if (mode == radialMode) {
handleRadialMode(event.x - mouseLastX, event.y - mouseLastY);
if (isActive && mode != noMode && !rotatingTowardsTarget) {
if (mode == radialMode) {
handleRadialMode(event.x - mouseLastX, event.y - mouseLastY);
}
if (mode == orbitMode) {
handleOrbitMode(event.x - mouseLastX, event.y - mouseLastY);
}
if (mode == panningMode) {
handlePanMode(event.x - mouseLastX, event.y - mouseLastY);
}
}
if (mode == orbitMode) {
handleOrbitMode(event.x - mouseLastX, event.y - mouseLastY);
}
if (mode == panningMode) {
handlePanMode(event.x - mouseLastX, event.y - mouseLastY);
}
}
mouseLastX = event.x;
mouseLastY = event.y;
mouseLastX = event.x;
mouseLastY = event.y;
}
function update() {
handleModes();
if (rotatingTowardsTarget) {
rotateTowardsTarget();
}
handleModes();
if (rotatingTowardsTarget) {
rotateTowardsTarget();
}
}
function rotateTowardsTarget() {
var newOrientation = Quat.mix(Camera.getOrientation(), targetCamOrientation, .1);
Camera.setOrientation(newOrientation);
var newOrientation = Quat.mix(Camera.getOrientation(), targetCamOrientation, 0.1);
Camera.setOrientation(newOrientation);
}
function scriptEnding() {
if (mode != noMode) {
restoreCameraState();
}
if (mode != noMode) {
restoreCameraState();
}
}
Controller.keyPressEvent.connect(keyPressEvent);
@ -345,4 +334,4 @@ Controller.mouseReleaseEvent.connect(mouseReleaseEvent);
Controller.mouseMoveEvent.connect(mouseMoveEvent);
Script.update.connect(update);
Script.scriptEnding.connect(scriptEnding);
Script.scriptEnding.connect(scriptEnding);

View file

@ -46,7 +46,6 @@ function onMuteClicked() {
printd("On Mute Clicked");
//Menu.setIsOptionChecked("Mute Microphone", !Menu.isOptionChecked("Mute Microphone"));
Audio.muted = !Audio.muted;
onMuteToggled();
}
function onMuteToggled() {

View file

@ -35,6 +35,7 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See
break;
case 'hide':
Controller.setVPadHidden(false);
module.exports.hide();
module.exports.onHidden();
break;
default:

View file

@ -33,7 +33,6 @@ function init() {
radar.setUniqueColor(uniqueColor);
radar.init();
setupModesBar();
radar.isTouchValid = isRadarModeValidTouch;
}
function shutdown() {
@ -183,34 +182,6 @@ function onButtonClicked(clickedButton, whatToDo, hideAllAfter) {
}
}
function isRadarModeValidTouch(coords) {
var qmlFragments = [modesbar.qmlFragment];
var windows = [];
for (var i=0; i < qmlFragments.length; i++) {
var aQmlFrag = qmlFragments[i];
if (aQmlFrag != null && aQmlFrag.isVisible() &&
coords.x >= aQmlFrag.position.x * 3 && coords.x <= aQmlFrag.position.x * 3 + aQmlFrag.size.x * 3 &&
coords.y >= aQmlFrag.position.y * 3 && coords.y <= aQmlFrag.position.y * 3 + aQmlFrag.size.y * 3
) {
printd("godViewModeTouchValid- false because of qmlFragments!? idx " + i);
return false;
}
}
for (var i=0; i < windows.length; i++) {
var aWin = windows[i];
if (aWin != null && aWin.position() != null &&
coords.x >= aWin.position().x * 3 && coords.x <= aWin.position().x * 3 + aWin.width() * 3 &&
coords.y >= aWin.position().y * 3 && coords.y <= aWin.position().y * 3 + aWin.height() * 3
) {
printd("godViewModeTouchValid- false because of windows!?");
return false;
}
}
printd("godViewModeTouchValid- true by default ");
return true;
}
Script.scriptEnding.connect(function () {
shutdown();
});

View file

@ -13,7 +13,7 @@
var radarModeInterface = {};
var logEnabled = true;
var logEnabled = false;
function printd(str) {
if (logEnabled) {
print("[radar.js] " + str);
@ -118,19 +118,10 @@ function actionOnObjectFromEvent(event) {
}
function mousePress(event) {
if (!isTouchValid(coords)) {
currentTouchIsValid = false;
return;
} else {
currentTouchIsValid = true;
}
mousePressOrTouchEnd(event);
}
function mousePressOrTouchEnd(event) {
if (!currentTouchIsValid) {
return;
}
if (radar) {
if (actionOnObjectFromEvent(event)) {
return;
@ -155,9 +146,6 @@ function fakeDoubleTap(event) {
teleporter.dragTeleportRelease(event);
}
var currentTouchIsValid = false; // Currently used to know if touch hasn't
// started on a UI overlay
var DOUBLE_TAP_TIME = 300;
var fakeDoubleTapStart = Date.now();
var touchEndCount = 0;
@ -238,12 +226,6 @@ function touchEnd(event) {
return;
}
// if touch is invalid, cancel
if (!currentTouchIsValid) {
printd("touchEnd fail because !currentTouchIsValid");
return;
}
if (analyzeDoubleTap(event))
return; // double tap detected, finish
@ -345,20 +327,6 @@ function computePointAtPlaneY(x, y, py) {
p2.z, py);
}
/*******************************************************************************
*
******************************************************************************/
function isTouchValid(coords) {
// TODO: Extend to the detection of touches on new menu bars
var radarModeTouchValid = radarModeInterface.isTouchValid(coords);
// getItemAtPoint does not exist anymore, look for another way to know if we
// are touching buttons
// is it still needed?
return /* !tablet.getItemAtPoint(coords) && */radarModeTouchValid;
}
/*******************************************************************************
*
******************************************************************************/
@ -373,16 +341,8 @@ function touchBegin(event) {
x : event.x,
y : event.y
};
if (!isTouchValid(coords)) {
printd("analyze touch - RADAR_TOUCH - INVALID");
currentTouchIsValid = false;
touchStartingCoordinates = null;
} else {
printd("analyze touch - RADAR_TOUCH - ok");
currentTouchIsValid = true;
touchStartingCoordinates = coords;
touchBeginTime = Date.now();
}
touchStartingCoordinates = coords;
touchBeginTime = Date.now();
}
var startedDraggingCamera = false; // first time
@ -848,9 +808,6 @@ function oneFingerTouchUpdate(event) {
}
function touchUpdate(event) {
if (!currentTouchIsValid) {
return; // avoid moving and zooming when tap is over UI entities
}
if (event.isPinching || event.isPinchOpening) {
pinchUpdate(event);
} else {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View file

@ -24,8 +24,9 @@ var OVERLAY_HEIGHT = 1080;
var OVERLAY_DATA = {
width: OVERLAY_WIDTH,
height: OVERLAY_HEIGHT,
imageURL: "http://hifi-content.s3.amazonaws.com/alan/production/images/images/Overlay-Viz-blank.png",
color: {red: 255, green: 255, blue: 255},
imageURL: Script.resolvePath("assets/images/Overlay-Viz-blank.png"),
emissive: true,
drawInFront: true,
alpha: 1
};
var AVATAR_MOVE_FOR_ACTIVE_DISTANCE = 0.8; // meters -- no longer away if avatar moves this far while away
@ -37,7 +38,7 @@ var OVERLAY_DATA_HMD = {
localRotation: {x: 0, y: 0, z: 0, w: 1},
width: OVERLAY_WIDTH,
height: OVERLAY_HEIGHT,
url: "http://hifi-content.s3.amazonaws.com/alan/production/images/images/Overlay-Viz-blank.png",
url: Script.resolvePath("assets/images/Overlay-Viz-blank.png"),
color: {red: 255, green: 255, blue: 255},
alpha: 1,
scale: 2 * MyAvatar.sensorToWorldScale,

View file

@ -307,6 +307,10 @@ WebTablet.prototype.setScriptURL = function (scriptURL) {
Overlays.editOverlay(this.webOverlayID, { scriptURL: scriptURL });
};
WebTablet.prototype.getOverlayObject = function () {
return Overlays.getOverlayObject(this.webOverlayID);
};
WebTablet.prototype.setWidth = function (width) {
// imported from libraries/utils.js
resizeTablet(width);