Merge branch 'master' into pointerEvents
39
.clang-format
Normal file
|
@ -0,0 +1,39 @@
|
|||
Language: Cpp
|
||||
Standard: Cpp11
|
||||
BasedOnStyle: "Chromium"
|
||||
ColumnLimit: 128
|
||||
IndentWidth: 4
|
||||
UseTab: Never
|
||||
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterEnum: true
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
SplitEmptyFunction: false
|
||||
SplitEmptyNamespace: true
|
||||
|
||||
|
||||
AccessModifierOffset: -4
|
||||
AllowShortFunctionsOnASingleLine: InlineOnly
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakConstructorInitializersBeforeComma: true
|
||||
IndentCaseLabels: true
|
||||
ReflowComments: false
|
||||
Cpp11BracedListStyle: false
|
||||
ContinuationIndentWidth: 4
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
CompactNamespaces: true
|
||||
SortIncludes: false
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
|
||||
PenaltyReturnTypeOnItsOwnLine: 1000
|
||||
PenaltyBreakBeforeFirstCallParameter: 1000
|
||||
|
2
BUILD.md
|
@ -25,7 +25,7 @@ The above dependencies will be downloaded, built, linked and included automatica
|
|||
|
||||
These are not placed in your normal build tree when doing an out of source build so that they do not need to be re-downloaded and re-compiled every time the CMake build folder is cleared. Should you want to force a re-download and re-compile of a specific external, you can simply remove that directory from the appropriate subfolder in `build/ext`. Should you want to force a re-download and re-compile of all externals, just remove the `build/ext` folder.
|
||||
|
||||
If you would like to use a specific install of a dependency instead of the version that would be grabbed as a CMake ExternalProject, you can pass -DUSE_LOCAL_$NAME=0 (where $NAME is the name of the subfolder in [cmake/externals](cmake/externals)) when you run CMake to tell it not to get that dependency as an external project.
|
||||
If you would like to use a specific install of a dependency instead of the version that would be grabbed as a CMake ExternalProject, you can pass -DUSE\_LOCAL\_$NAME=0 (where $NAME is the name of the subfolder in [cmake/externals](cmake/externals)) when you run CMake to tell it not to get that dependency as an external project.
|
||||
|
||||
### OS Specific Build Guides
|
||||
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
#include <UUID.h>
|
||||
#include <WebSocketServerClass.h>
|
||||
|
||||
#include <EntityScriptClient.h> // for EntityScriptServerServices
|
||||
|
||||
#include "EntityScriptServerLogging.h"
|
||||
#include "../entities/AssignmentParentFinder.h"
|
||||
|
||||
|
@ -68,6 +70,9 @@ EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : ThreadedAssig
|
|||
DependencyManager::set<ScriptCache>();
|
||||
DependencyManager::set<ScriptEngines>(ScriptEngine::ENTITY_SERVER_SCRIPT);
|
||||
|
||||
DependencyManager::set<EntityScriptServerServices>();
|
||||
|
||||
|
||||
// Needed to ensure the creation of the DebugDraw instance on the main thread
|
||||
DebugDraw::getInstance();
|
||||
|
||||
|
@ -85,6 +90,7 @@ EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : ThreadedAssig
|
|||
packetReceiver.registerListener(PacketType::ReloadEntityServerScript, this, "handleReloadEntityServerScriptPacket");
|
||||
packetReceiver.registerListener(PacketType::EntityScriptGetStatus, this, "handleEntityScriptGetStatusPacket");
|
||||
packetReceiver.registerListener(PacketType::EntityServerScriptLog, this, "handleEntityServerScriptLogPacket");
|
||||
packetReceiver.registerListener(PacketType::EntityScriptCallMethod, this, "handleEntityScriptCallMethodPacket");
|
||||
|
||||
static const int LOG_INTERVAL = MSECS_PER_SECOND / 10;
|
||||
auto timer = new QTimer(this);
|
||||
|
@ -231,6 +237,27 @@ void EntityScriptServer::pushLogs() {
|
|||
}
|
||||
}
|
||||
|
||||
void EntityScriptServer::handleEntityScriptCallMethodPacket(QSharedPointer<ReceivedMessage> receivedMessage, SharedNodePointer senderNode) {
|
||||
|
||||
if (_entitiesScriptEngine && _entityViewer.getTree() && !_shuttingDown) {
|
||||
auto entityID = QUuid::fromRfc4122(receivedMessage->read(NUM_BYTES_RFC4122_UUID));
|
||||
|
||||
auto method = receivedMessage->readString();
|
||||
|
||||
quint16 paramCount;
|
||||
receivedMessage->readPrimitive(¶mCount);
|
||||
|
||||
QStringList params;
|
||||
for (int param = 0; param < paramCount; param++) {
|
||||
auto paramString = receivedMessage->readString();
|
||||
params << paramString;
|
||||
}
|
||||
|
||||
_entitiesScriptEngine->callEntityScriptMethod(entityID, method, params, senderNode->getUUID());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EntityScriptServer::run() {
|
||||
// make sure we request our script once the agent connects to the domain
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
|
@ -561,6 +588,7 @@ void EntityScriptServer::aboutToFinish() {
|
|||
// cleanup the AudioInjectorManager (and any still running injectors)
|
||||
DependencyManager::destroy<AudioInjectorManager>();
|
||||
DependencyManager::destroy<ScriptEngines>();
|
||||
DependencyManager::destroy<EntityScriptServerServices>();
|
||||
|
||||
// cleanup codec & encoder
|
||||
if (_codec && _encoder) {
|
||||
|
|
|
@ -54,6 +54,9 @@ private slots:
|
|||
|
||||
void pushLogs();
|
||||
|
||||
void handleEntityScriptCallMethodPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
||||
|
||||
|
||||
private:
|
||||
void negotiateAudioFormat();
|
||||
void selectAudioFormat(const QString& selectedCodecName);
|
||||
|
|
|
@ -118,6 +118,7 @@ macro(AUTOSCRIBE_SHADER_LIB)
|
|||
foreach(SHADER_FILE ${SHADER_SOURCE_FILES})
|
||||
AUTOSCRIBE_SHADER(${SHADER_FILE} ${SHADER_INCLUDE_FILES})
|
||||
file(TO_CMAKE_PATH "${AUTOSCRIBE_SHADER_RETURN}" AUTOSCRIBE_GENERATED_FILE)
|
||||
set_property(SOURCE ${AUTOSCRIBE_GENERATED_FILE} PROPERTY SKIP_AUTOMOC ON)
|
||||
list(APPEND AUTOSCRIBE_SHADER_SRC ${AUTOSCRIBE_GENERATED_FILE})
|
||||
endforeach()
|
||||
#message(${TARGET_NAME} ${AUTOSCRIBE_SHADER_SRC})
|
||||
|
|
20
cmake/macros/GenerateQrc.cmake
Normal file
|
@ -0,0 +1,20 @@
|
|||
|
||||
function(GENERATE_QRC)
|
||||
set(oneValueArgs OUTPUT PREFIX PATH)
|
||||
set(multiValueArgs GLOBS)
|
||||
cmake_parse_arguments(GENERATE_QRC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
|
||||
if ("${GENERATE_QRC_PREFIX}" STREQUAL "")
|
||||
set(QRC_PREFIX_PATH /)
|
||||
else()
|
||||
set(QRC_PREFIX_PATH ${GENERATE_QRC_PREFIX})
|
||||
endif()
|
||||
|
||||
foreach(GLOB ${GENERATE_QRC_GLOBS})
|
||||
file(GLOB_RECURSE FOUND_FILES RELATIVE ${GENERATE_QRC_PATH} ${GLOB})
|
||||
foreach(FILENAME ${FOUND_FILES})
|
||||
set(QRC_CONTENTS "${QRC_CONTENTS}<file alias=\"${FILENAME}\">${GENERATE_QRC_PATH}/${FILENAME}</file>\n")
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
configure_file("${HF_CMAKE_DIR}/templates/resources.qrc.in" ${GENERATE_QRC_OUTPUT})
|
||||
endfunction()
|
|
@ -7,10 +7,12 @@
|
|||
#
|
||||
|
||||
function(set_from_env _RESULT_NAME _ENV_VAR_NAME _DEFAULT_VALUE)
|
||||
if ("$ENV{${_ENV_VAR_NAME}}" STREQUAL "")
|
||||
set (${_RESULT_NAME} ${_DEFAULT_VALUE} PARENT_SCOPE)
|
||||
else()
|
||||
set (${_RESULT_NAME} $ENV{${_ENV_VAR_NAME}} PARENT_SCOPE)
|
||||
if (NOT DEFINED ${_RESULT_NAME})
|
||||
if ("$ENV{${_ENV_VAR_NAME}}" STREQUAL "")
|
||||
set (${_RESULT_NAME} ${_DEFAULT_VALUE} PARENT_SCOPE)
|
||||
else()
|
||||
set (${_RESULT_NAME} $ENV{${_ENV_VAR_NAME}} PARENT_SCOPE)
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
|
|
5
cmake/templates/resources.qrc.in
Normal file
|
@ -0,0 +1,5 @@
|
|||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource prefix="@QRC_PREFIX_PATH@">
|
||||
@QRC_CONTENTS@
|
||||
</qresource>
|
||||
</RCC>
|
|
@ -1,6 +1,20 @@
|
|||
set(TARGET_NAME interface)
|
||||
project(${TARGET_NAME})
|
||||
|
||||
file(GLOB_RECURSE QML_SRC resources/qml/*.qml resources/qml/*.js)
|
||||
add_custom_target(qml SOURCES ${QML_SRC})
|
||||
GroupSources("resources/qml")
|
||||
|
||||
function(JOIN VALUES GLUE OUTPUT)
|
||||
string (REGEX REPLACE "([^\\]|^);" "\\1${GLUE}" _TMP_STR "${VALUES}")
|
||||
string (REGEX REPLACE "[\\](.)" "\\1" _TMP_STR "${_TMP_STR}") #fixes escaping
|
||||
set (${OUTPUT} "${_TMP_STR}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
|
||||
set(INTERFACE_QML_QRC ${CMAKE_CURRENT_BINARY_DIR}/qml.qrc)
|
||||
generate_qrc(OUTPUT ${INTERFACE_QML_QRC} PATH ${CMAKE_CURRENT_SOURCE_DIR}/resources GLOBS *.qml *.qss *.js *.html *.ttf *.gif *.svg *.png *.jpg)
|
||||
|
||||
# set a default root dir for each of our optional externals if it was not passed
|
||||
set(OPTIONAL_EXTERNALS "LeapMotion")
|
||||
|
||||
|
@ -66,9 +80,7 @@ qt5_wrap_ui(QT_UI_HEADERS "${QT_UI_FILES}")
|
|||
# add them to the interface source files
|
||||
set(INTERFACE_SRCS ${INTERFACE_SRCS} "${QT_UI_HEADERS}" "${QT_RESOURCES}")
|
||||
|
||||
file(GLOB_RECURSE QML_SRC resources/qml/*.qml resources/qml/*.js)
|
||||
add_custom_target(qml SOURCES ${QML_SRC})
|
||||
GroupSources("resources/qml")
|
||||
list(APPEND INTERFACE_SRCS ${INTERFACE_QML_QRC})
|
||||
|
||||
if (UNIX)
|
||||
install(
|
||||
|
@ -131,10 +143,10 @@ if (APPLE)
|
|||
|
||||
# append the discovered resources to our list of interface sources
|
||||
list(APPEND INTERFACE_SRCS ${DISCOVERED_RESOURCES})
|
||||
|
||||
set(INTERFACE_SRCS ${INTERFACE_SRCS} "${CMAKE_CURRENT_SOURCE_DIR}/icon/${INTERFACE_ICON_FILENAME}")
|
||||
list(APPEND INTERFACE_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/icon/${INTERFACE_ICON_FILENAME})
|
||||
endif()
|
||||
|
||||
|
||||
# create the executable, make it a bundle on OS X
|
||||
if (APPLE)
|
||||
add_executable(${TARGET_NAME} MACOSX_BUNDLE ${INTERFACE_SRCS} ${QM})
|
||||
|
@ -198,6 +210,7 @@ endif()
|
|||
# link required hifi libraries
|
||||
link_hifi_libraries(
|
||||
shared octree ktx gpu gl gpu-gl procedural model render
|
||||
pointers
|
||||
recording fbx networking model-networking entities avatars trackers
|
||||
audio audio-client animation script-engine physics
|
||||
render-utils entities-renderer avatars-renderer ui auto-updater midi
|
||||
|
|
Before ![]() (image error) Size: 312 KiB After ![]() (image error) Size: 604 KiB ![]() ![]() |
Before ![]() (image error) Size: 232 KiB After ![]() (image error) Size: 503 KiB ![]() ![]() |
Before ![]() (image error) Size: 307 KiB After ![]() (image error) Size: 585 KiB ![]() ![]() |
Before ![]() (image error) Size: 268 KiB After ![]() (image error) Size: 547 KiB ![]() ![]() |
|
@ -14,11 +14,17 @@
|
|||
var isWindowFocused = true;
|
||||
var isKeyboardRaised = false;
|
||||
var isNumericKeyboard = false;
|
||||
var isPasswordField = false;
|
||||
|
||||
function shouldSetPasswordField() {
|
||||
var nodeType = document.activeElement.type;
|
||||
return nodeType === "password";
|
||||
}
|
||||
|
||||
function shouldRaiseKeyboard() {
|
||||
var nodeName = document.activeElement.nodeName;
|
||||
var nodeType = document.activeElement.type;
|
||||
if (nodeName === "INPUT" && ["email", "number", "password", "tel", "text", "url"].indexOf(nodeType) !== -1
|
||||
if (nodeName === "INPUT" && ["email", "number", "password", "tel", "text", "url", "search"].indexOf(nodeType) !== -1
|
||||
|| document.activeElement.nodeName === "TEXTAREA") {
|
||||
return true;
|
||||
} else {
|
||||
|
@ -53,12 +59,14 @@
|
|||
setInterval(function () {
|
||||
var keyboardRaised = shouldRaiseKeyboard();
|
||||
var numericKeyboard = shouldSetNumeric();
|
||||
var passwordField = shouldSetPasswordField();
|
||||
|
||||
if (isWindowFocused && (keyboardRaised !== isKeyboardRaised || numericKeyboard !== isNumericKeyboard)) {
|
||||
if (isWindowFocused &&
|
||||
(keyboardRaised !== isKeyboardRaised || numericKeyboard !== isNumericKeyboard || passwordField !== isPasswordField)) {
|
||||
|
||||
if (typeof EventBridge !== "undefined" && EventBridge !== null) {
|
||||
EventBridge.emitWebEvent(
|
||||
keyboardRaised ? ("_RAISE_KEYBOARD" + (numericKeyboard ? "_NUMERIC" : "")) : "_LOWER_KEYBOARD"
|
||||
keyboardRaised ? ("_RAISE_KEYBOARD" + (numericKeyboard ? "_NUMERIC" : "") + (passwordField ? "_PASSWORD" : "")) : "_LOWER_KEYBOARD"
|
||||
);
|
||||
} else {
|
||||
if (numWarnings < MAX_WARNINGS) {
|
||||
|
@ -74,6 +82,7 @@
|
|||
|
||||
isKeyboardRaised = keyboardRaised;
|
||||
isNumericKeyboard = numericKeyboard;
|
||||
isPasswordField = passwordField;
|
||||
}
|
||||
}, POLL_FREQUENCY);
|
||||
|
||||
|
|
|
@ -119,6 +119,7 @@ Item {
|
|||
width: parent.width
|
||||
focus: true
|
||||
label: "Username or Email"
|
||||
activeFocusOnPress: true
|
||||
|
||||
ShortcutText {
|
||||
anchors {
|
||||
|
@ -135,6 +136,9 @@ Item {
|
|||
|
||||
onLinkActivated: loginDialog.openUrl(link)
|
||||
}
|
||||
onFocusChanged: {
|
||||
root.text = "";
|
||||
}
|
||||
}
|
||||
|
||||
TextField {
|
||||
|
@ -143,6 +147,7 @@ Item {
|
|||
|
||||
label: "Password"
|
||||
echoMode: showPassword.checked ? TextInput.Normal : TextInput.Password
|
||||
activeFocusOnPress: true
|
||||
|
||||
ShortcutText {
|
||||
anchors {
|
||||
|
@ -159,6 +164,10 @@ Item {
|
|||
|
||||
onLinkActivated: loginDialog.openUrl(link)
|
||||
}
|
||||
onFocusChanged: {
|
||||
root.text = "";
|
||||
root.isPassword = true;
|
||||
}
|
||||
}
|
||||
|
||||
CheckBoxQQC2 {
|
||||
|
@ -233,18 +242,6 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
// Override ScrollingWindow's keyboard that would be at very bottom of dialog.
|
||||
Keyboard {
|
||||
raised: keyboardEnabled && keyboardRaised
|
||||
numeric: punctuationMode
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
bottomMargin: keyboardRaised ? 2 * hifi.dimensions.contentSpacing.y : 0
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
root.title = qsTr("Sign Into High Fidelity")
|
||||
root.iconText = "<"
|
||||
|
|
|
@ -108,12 +108,17 @@ Item {
|
|||
id: emailField
|
||||
width: parent.width
|
||||
label: "Email"
|
||||
activeFocusOnPress: true
|
||||
onFocusChanged: {
|
||||
root.text = "";
|
||||
}
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: usernameField
|
||||
width: parent.width
|
||||
label: "Username"
|
||||
activeFocusOnPress: true
|
||||
|
||||
ShortcutText {
|
||||
anchors {
|
||||
|
@ -128,6 +133,9 @@ Item {
|
|||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
color: hifi.colors.blueAccent
|
||||
onFocusChanged: {
|
||||
root.text = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -136,6 +144,7 @@ Item {
|
|||
width: parent.width
|
||||
label: "Password"
|
||||
echoMode: TextInput.Password
|
||||
activeFocusOnPress: true
|
||||
|
||||
ShortcutText {
|
||||
anchors {
|
||||
|
@ -151,6 +160,11 @@ Item {
|
|||
|
||||
color: hifi.colors.blueAccent
|
||||
}
|
||||
|
||||
onFocusChanged: {
|
||||
root.text = "";
|
||||
root.isPassword = focus
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
|
@ -202,18 +216,6 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
// Override ScrollingWindow's keyboard that would be at very bottom of dialog.
|
||||
Keyboard {
|
||||
raised: keyboardEnabled && keyboardRaised
|
||||
numeric: punctuationMode
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
bottomMargin: keyboardRaised ? 2 * hifi.dimensions.contentSpacing.y : 0
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
root.title = qsTr("Create an Account")
|
||||
root.iconText = "<"
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4 as Original
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import TabletScriptingInterface 1.0
|
||||
|
||||
import "../styles-uit"
|
||||
|
||||
|
@ -26,6 +27,16 @@ Original.Button {
|
|||
|
||||
HifiConstants { id: hifi }
|
||||
|
||||
onHoveredChanged: {
|
||||
if (hovered) {
|
||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
||||
}
|
||||
|
||||
style: ButtonStyle {
|
||||
|
||||
background: Rectangle {
|
||||
|
|
|
@ -14,6 +14,8 @@ import QtQuick.Controls.Styles 1.4
|
|||
|
||||
import "../styles-uit"
|
||||
|
||||
import TabletScriptingInterface 1.0
|
||||
|
||||
Original.CheckBox {
|
||||
id: checkBox
|
||||
|
||||
|
@ -28,6 +30,15 @@ Original.CheckBox {
|
|||
readonly property int checkRadius: 2
|
||||
activeFocusOnPress: true
|
||||
|
||||
onClicked: {
|
||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
||||
}
|
||||
|
||||
// TODO: doesnt works for QQC1. check with QQC2
|
||||
// onHovered: {
|
||||
// tabletInterface.playSound(TabletEnums.ButtonHover);
|
||||
// }
|
||||
|
||||
style: CheckBoxStyle {
|
||||
indicator: Rectangle {
|
||||
id: box
|
||||
|
|
|
@ -13,6 +13,7 @@ import QtQuick.Controls 2.2
|
|||
|
||||
import "../styles-uit"
|
||||
import "../controls-uit" as HiFiControls
|
||||
import TabletScriptingInterface 1.0
|
||||
|
||||
CheckBox {
|
||||
id: checkBox
|
||||
|
@ -32,6 +33,17 @@ CheckBox {
|
|||
readonly property int checkSize: Math.max(boxSize - 8, 10)
|
||||
readonly property int checkRadius: isRound ? checkSize / 2 : 2
|
||||
focusPolicy: Qt.ClickFocus
|
||||
hoverEnabled: true
|
||||
|
||||
onClicked: {
|
||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
||||
}
|
||||
|
||||
onHoveredChanged: {
|
||||
if (hovered) {
|
||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
||||
}
|
||||
}
|
||||
|
||||
indicator: Rectangle {
|
||||
id: box
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4 as Original
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import TabletScriptingInterface 1.0
|
||||
|
||||
import "../styles-uit"
|
||||
|
||||
|
@ -24,6 +25,16 @@ Original.Button {
|
|||
width: 120
|
||||
height: 28
|
||||
|
||||
onHoveredChanged: {
|
||||
if (hovered) {
|
||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
||||
}
|
||||
|
||||
style: ButtonStyle {
|
||||
|
||||
background: Rectangle {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import QtQuick 2.0
|
||||
import TabletScriptingInterface 1.0
|
||||
|
||||
Item {
|
||||
id: keyItem
|
||||
|
@ -32,8 +33,15 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
onContainsMouseChanged: {
|
||||
if (containsMouse) {
|
||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
mouse.accepted = true;
|
||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
||||
|
||||
webEntity.synthesizeKeyPress(glyph);
|
||||
webEntity.synthesizeKeyPress(glyph, mirrorText);
|
||||
|
|
|
@ -13,6 +13,7 @@ import "."
|
|||
|
||||
Rectangle {
|
||||
id: keyboardBase
|
||||
objectName: "keyboard"
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
@ -27,6 +28,8 @@ Rectangle {
|
|||
|
||||
readonly property int mirrorTextHeight: keyboardRowHeight
|
||||
|
||||
property bool password: false
|
||||
property alias mirroredText: mirrorText.text
|
||||
property bool showMirrorText: true
|
||||
readonly property int raisedHeight: 200
|
||||
|
||||
|
@ -36,6 +39,10 @@ Rectangle {
|
|||
property bool shiftMode: false
|
||||
property bool numericShiftMode: false
|
||||
|
||||
onRaisedChanged: {
|
||||
mirroredText = "";
|
||||
}
|
||||
|
||||
function resetShiftMode(mode) {
|
||||
shiftMode = mode;
|
||||
shiftKey.resetToggledMode(mode);
|
||||
|
@ -112,16 +119,20 @@ Rectangle {
|
|||
color: "#252525"
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
TextEdit {
|
||||
TextInput {
|
||||
id: mirrorText
|
||||
visible: showMirrorText
|
||||
size: 13.5
|
||||
FontLoader { id: ralewaySemiBold; source: "../../fonts/Raleway-SemiBold.ttf"; }
|
||||
font.family: ralewaySemiBold.name
|
||||
font.pointSize: 13.5
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
color: "#FFFFFF";
|
||||
anchors.fill: parent
|
||||
wrapMode: Text.WordWrap
|
||||
readOnly: false // we need to leave this property read-only to allow control to accept QKeyEvent
|
||||
readOnly: false // we need this to allow control to accept QKeyEvent
|
||||
selectByMouse: false
|
||||
echoMode: password ? TextInput.Password : TextInput.Normal
|
||||
|
||||
Keys.onPressed: {
|
||||
if (event.key == Qt.Key_Return || event.key == Qt.Key_Space) {
|
||||
|
|
|
@ -15,6 +15,8 @@ import QtQuick.Controls.Styles 1.4
|
|||
import "../styles-uit"
|
||||
import "../controls-uit" as HifiControls
|
||||
|
||||
import TabletScriptingInterface 1.0
|
||||
|
||||
Original.RadioButton {
|
||||
id: radioButton
|
||||
HifiConstants { id: hifi }
|
||||
|
@ -27,6 +29,15 @@ Original.RadioButton {
|
|||
readonly property int checkSize: 10
|
||||
readonly property int checkRadius: 2
|
||||
|
||||
onClicked: {
|
||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
||||
}
|
||||
|
||||
// TODO: doesnt works for QQC1. check with QQC2
|
||||
// onHovered: {
|
||||
// tabletInterface.playSound(TabletEnums.ButtonHover);
|
||||
// }
|
||||
|
||||
style: RadioButtonStyle {
|
||||
indicator: Rectangle {
|
||||
id: box
|
||||
|
|
|
@ -16,6 +16,7 @@ Item {
|
|||
property bool keyboardEnabled: false
|
||||
property bool keyboardRaised: false
|
||||
property bool punctuationMode: false
|
||||
property bool passwordField: false
|
||||
property bool isDesktop: false
|
||||
property alias webView: web.webViewCore
|
||||
property alias profile: web.webViewCoreProfile
|
||||
|
@ -41,7 +42,7 @@ Item {
|
|||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
spacing: 120
|
||||
|
||||
|
||||
TabletWebButton {
|
||||
id: back
|
||||
enabledColor: hifi.colors.darkGray
|
||||
|
@ -165,6 +166,11 @@ Item {
|
|||
id: keyboard
|
||||
raised: parent.keyboardEnabled && parent.keyboardRaised
|
||||
numeric: parent.punctuationMode
|
||||
password: parent.passwordField
|
||||
|
||||
onPasswordChanged: {
|
||||
keyboard.mirroredText = "";
|
||||
}
|
||||
|
||||
anchors {
|
||||
left: parent.left
|
||||
|
@ -172,7 +178,7 @@ Item {
|
|||
bottom: parent.bottom
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Component.onCompleted: {
|
||||
root.isDesktop = (typeof desktop !== "undefined");
|
||||
keyboardEnabled = HMD.active;
|
||||
|
|
|
@ -13,6 +13,7 @@ Item {
|
|||
property bool keyboardEnabled: true // FIXME - Keyboard HMD only: Default to false
|
||||
property bool keyboardRaised: false
|
||||
property bool punctuationMode: false
|
||||
property bool passwordField: false
|
||||
property alias flickable: webroot.interactive
|
||||
|
||||
// FIXME - Keyboard HMD only: Make Interface either set keyboardRaised property directly in OffscreenQmlSurface
|
||||
|
@ -50,6 +51,7 @@ Item {
|
|||
id: keyboard
|
||||
raised: parent.keyboardEnabled && parent.keyboardRaised
|
||||
numeric: parent.punctuationMode
|
||||
password: parent.passwordField
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
|
|
|
@ -37,6 +37,8 @@ TabletModalWindow {
|
|||
property bool keyboardEnabled: false
|
||||
property bool keyboardRaised: false
|
||||
property bool punctuationMode: false
|
||||
property bool isPassword: false
|
||||
property alias text: loginKeyboard.mirroredText
|
||||
|
||||
readonly property bool isTablet: true
|
||||
|
||||
|
@ -130,6 +132,7 @@ TabletModalWindow {
|
|||
id: loginKeyboard
|
||||
raised: root.keyboardEnabled && root.keyboardRaised
|
||||
numeric: root.punctuationMode
|
||||
password: root.isPassword
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import TabletScriptingInterface 1.0
|
||||
|
||||
import "../../controls-uit"
|
||||
|
||||
|
@ -22,7 +23,16 @@ Preference {
|
|||
|
||||
Button {
|
||||
id: button
|
||||
onClicked: preference.trigger()
|
||||
onHoveredChanged: {
|
||||
if (hovered) {
|
||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
preference.trigger();
|
||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
||||
}
|
||||
width: 180
|
||||
anchors.bottom: parent.bottom
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import TabletScriptingInterface 1.0
|
||||
|
||||
import "../../controls-uit"
|
||||
|
||||
|
@ -38,6 +39,16 @@ Preference {
|
|||
|
||||
CheckBox {
|
||||
id: checkBox
|
||||
onHoveredChanged: {
|
||||
if (hovered) {
|
||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
||||
}
|
||||
|
||||
anchors {
|
||||
top: spacer.bottom
|
||||
left: parent.left
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
import Hifi 1.0
|
||||
import QtQuick 2.5
|
||||
import QtGraphicalEffects 1.0
|
||||
import TabletScriptingInterface 1.0
|
||||
|
||||
import "toolbars"
|
||||
import "../styles-uit"
|
||||
|
||||
|
@ -243,9 +245,15 @@ Item {
|
|||
MouseArea {
|
||||
anchors.fill: parent;
|
||||
acceptedButtons: Qt.LeftButton;
|
||||
onClicked: goFunction("hifi://" + hifiUrl);
|
||||
onClicked: {
|
||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
||||
goFunction("hifi://" + hifiUrl);
|
||||
}
|
||||
hoverEnabled: true;
|
||||
onEntered: hoverThunk();
|
||||
onEntered: {
|
||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
||||
hoverThunk();
|
||||
}
|
||||
onExited: unhoverThunk();
|
||||
}
|
||||
StateImage {
|
||||
|
@ -261,6 +269,7 @@ Item {
|
|||
}
|
||||
}
|
||||
function go() {
|
||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
||||
goFunction(drillDownToPlace ? ("/places/" + placeName) : ("/user_stories/" + storyId));
|
||||
}
|
||||
MouseArea {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// skyboxchanger.qml
|
||||
//
|
||||
// SkyboxChanger.qml
|
||||
// qml/hifi
|
||||
//
|
||||
// Created by Cain Kilgore on 9th August 2017
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
|
@ -9,33 +9,73 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick.Layouts 1.3
|
||||
import QtQuick 2.5
|
||||
import "../styles-uit"
|
||||
import "../controls-uit" as HifiControls
|
||||
import QtQuick.Controls 2.2
|
||||
|
||||
Rectangle {
|
||||
Item {
|
||||
id: root;
|
||||
|
||||
color: hifi.colors.baseGray;
|
||||
|
||||
HifiConstants { id: hifi; }
|
||||
|
||||
property var defaultThumbnails: [];
|
||||
property var defaultFulls: [];
|
||||
|
||||
ListModel {
|
||||
id: skyboxModel;
|
||||
}
|
||||
|
||||
function getSkyboxes() {
|
||||
var xmlhttp = new XMLHttpRequest();
|
||||
var url = "http://mpassets.highfidelity.com/5fbdbeef-1cf8-4954-811d-3d4acbba4dc9-v1/skyboxes.json";
|
||||
xmlhttp.onreadystatechange = function() {
|
||||
if (xmlhttp.readyState === XMLHttpRequest.DONE && xmlhttp.status === 200) {
|
||||
sortSkyboxes(xmlhttp.responseText);
|
||||
}
|
||||
}
|
||||
xmlhttp.open("GET", url, true);
|
||||
xmlhttp.send();
|
||||
}
|
||||
|
||||
function sortSkyboxes(response) {
|
||||
var arr = JSON.parse(response);
|
||||
var arrLength = arr.length;
|
||||
for (var i = 0; i < arrLength; i++) {
|
||||
defaultThumbnails.push(arr[i].thumb);
|
||||
defaultFulls.push(arr[i].full);
|
||||
skyboxModel.append({});
|
||||
}
|
||||
setSkyboxes();
|
||||
}
|
||||
|
||||
function setSkyboxes() {
|
||||
for (var i = 0; i < skyboxModel.count; i++) {
|
||||
skyboxModel.setProperty(i, "thumbnailPath", defaultThumbnails[i]);
|
||||
skyboxModel.setProperty(i, "fullSkyboxPath", defaultFulls[i]);
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
getSkyboxes();
|
||||
}
|
||||
|
||||
Item {
|
||||
id: titleBarContainer;
|
||||
// Size
|
||||
width: parent.width;
|
||||
height: 50;
|
||||
// Anchors
|
||||
height: childrenRect.height;
|
||||
anchors.left: parent.left;
|
||||
anchors.top: parent.top;
|
||||
|
||||
RalewaySemiBold {
|
||||
anchors.right: parent.right;
|
||||
anchors.topMargin: 20;
|
||||
RalewayBold {
|
||||
id: titleBarText;
|
||||
text: "Skybox Changer";
|
||||
// Text size
|
||||
size: hifi.fontSizes.overlayTitle;
|
||||
// Anchors
|
||||
anchors.fill: parent;
|
||||
anchors.leftMargin: 16;
|
||||
// Style
|
||||
anchors.top: parent.top;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 40
|
||||
height: paintedHeight;
|
||||
color: hifi.colors.lightGrayText;
|
||||
// Alignment
|
||||
horizontalAlignment: Text.AlignHCenter;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
}
|
||||
|
@ -43,131 +83,61 @@ Rectangle {
|
|||
id: titleBarDesc;
|
||||
text: "Click an image to choose a new Skybox.";
|
||||
wrapMode: Text.Wrap
|
||||
// Text size
|
||||
size: 14;
|
||||
// Anchors
|
||||
anchors.fill: parent;
|
||||
anchors.top: titleBarText.bottom
|
||||
anchors.leftMargin: 16;
|
||||
anchors.rightMargin: 16;
|
||||
// Style
|
||||
anchors.top: titleBarText.bottom;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 40
|
||||
height: paintedHeight;
|
||||
color: hifi.colors.lightGrayText;
|
||||
// Alignment
|
||||
horizontalAlignment: Text.AlignHCenter;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This RowLayout could be a GridLayout instead for further expandability.
|
||||
// As this SkyboxChanger task only required 6 images, implementing GridLayout wasn't necessary.
|
||||
// In the future if this is to be expanded to add more Skyboxes, it might be worth changing this.
|
||||
RowLayout {
|
||||
id: row1
|
||||
GridView {
|
||||
id: gridView
|
||||
interactive: true
|
||||
clip: true
|
||||
anchors.top: titleBarContainer.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 30
|
||||
Layout.fillWidth: true
|
||||
anchors.topMargin: 30
|
||||
spacing: 10
|
||||
Image {
|
||||
width: 200; height: 200
|
||||
fillMode: Image.Stretch
|
||||
source: "http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/thumbnails/thumb_1.jpg"
|
||||
clip: true
|
||||
id: preview1
|
||||
MouseArea {
|
||||
anchors.topMargin: 20
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: 400
|
||||
anchors.bottom: parent.bottom
|
||||
currentIndex: -1
|
||||
cellWidth: 200
|
||||
cellHeight: 200
|
||||
model: skyboxModel
|
||||
delegate: Item {
|
||||
width: gridView.cellWidth
|
||||
height: gridView.cellHeight
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
sendToScript({method: 'changeSkybox', url: 'http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/skyboxes/1.jpg'});
|
||||
Image {
|
||||
source: thumbnailPath
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
fillMode: Image.Stretch
|
||||
sourceSize.width: parent.width
|
||||
sourceSize.height: parent.height
|
||||
mipmap: true
|
||||
}
|
||||
}
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
Image {
|
||||
width: 200; height: 200
|
||||
fillMode: Image.Stretch
|
||||
source: "http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/thumbnails/thumb_2.jpg"
|
||||
clip: true
|
||||
id: preview2
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
sendToScript({method: 'changeSkybox', url: 'http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/skyboxes/2.png'});
|
||||
sendToScript({method: 'changeSkybox', url: fullSkyboxPath});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
RowLayout {
|
||||
id: row2
|
||||
anchors.top: row1.bottom
|
||||
anchors.topMargin: 10
|
||||
anchors.left: parent.left
|
||||
Layout.fillWidth: true
|
||||
anchors.leftMargin: 30
|
||||
spacing: 10
|
||||
Image {
|
||||
width: 200; height: 200
|
||||
fillMode: Image.Stretch
|
||||
source: "http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/thumbnails/thumb_3.jpg"
|
||||
clip: true
|
||||
id: preview3
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
sendToScript({method: 'changeSkybox', url: 'http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/skyboxes/3.jpg'});
|
||||
}
|
||||
}
|
||||
}
|
||||
Image {
|
||||
width: 200; height: 200
|
||||
fillMode: Image.Stretch
|
||||
source: "http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/thumbnails/thumb_4.jpg"
|
||||
clip: true
|
||||
id: preview4
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
sendToScript({method: 'changeSkybox', url: 'http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/skyboxes/4.jpg'});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
RowLayout {
|
||||
id: row3
|
||||
anchors.top: row2.bottom
|
||||
anchors.topMargin: 10
|
||||
anchors.left: parent.left
|
||||
Layout.fillWidth: true
|
||||
anchors.leftMargin: 30
|
||||
spacing: 10
|
||||
Image {
|
||||
width: 200; height: 200
|
||||
fillMode: Image.Stretch
|
||||
source: "http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/thumbnails/thumb_5.jpg"
|
||||
clip: true
|
||||
id: preview5
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
sendToScript({method: 'changeSkybox', url: 'http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/skyboxes/5.png'});
|
||||
}
|
||||
}
|
||||
}
|
||||
Image {
|
||||
width: 200; height: 200
|
||||
fillMode: Image.Stretch
|
||||
source: "http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/thumbnails/thumb_6.jpg"
|
||||
clip: true
|
||||
id: preview6
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
sendToScript({method: 'changeSkybox', url: 'http://mpassets.highfidelity.com/05904016-8f7d-4dfc-88e1-2bf9ba3fac20-v1/skyboxes/6.jpg'});
|
||||
}
|
||||
}
|
||||
ScrollBar.vertical: ScrollBar {
|
||||
parent: gridView.parent
|
||||
anchors.top: gridView.top
|
||||
anchors.left: gridView.right
|
||||
anchors.bottom: gridView.bottom
|
||||
anchors.leftMargin: 10
|
||||
width: 19
|
||||
}
|
||||
}
|
||||
|
||||
signal sendToScript(var message);
|
||||
|
||||
}
|
||||
}
|
|
@ -14,6 +14,8 @@ import QtQuick.Controls 1.4
|
|||
import QtQuick.Layouts 1.3
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
import TabletScriptingInterface 1.0
|
||||
|
||||
Rectangle {
|
||||
readonly property var level: Audio.inputLevel;
|
||||
|
||||
|
@ -57,8 +59,16 @@ Rectangle {
|
|||
|
||||
hoverEnabled: true;
|
||||
scrollGestureEnabled: false;
|
||||
onClicked: { Audio.muted = !Audio.muted; }
|
||||
onClicked: {
|
||||
Audio.muted = !Audio.muted;
|
||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
||||
}
|
||||
drag.target: dragTarget;
|
||||
onContainsMouseChanged: {
|
||||
if (containsMouse) {
|
||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QtObject {
|
||||
|
|
|
@ -39,7 +39,8 @@ Rectangle {
|
|||
property bool itemIsJson: true;
|
||||
property bool shouldBuyWithControlledFailure: false;
|
||||
property bool debugCheckoutSuccess: false;
|
||||
property bool canRezCertifiedItems: Entities.canRezCertified || Entities.canRezTmpCertified;
|
||||
property bool canRezCertifiedItems: Entities.canRezCertified() || Entities.canRezTmpCertified();
|
||||
property bool isWearable;
|
||||
// Style
|
||||
color: hifi.colors.white;
|
||||
Hifi.QmlCommerce {
|
||||
|
@ -80,6 +81,7 @@ Rectangle {
|
|||
root.activeView = "checkoutFailure";
|
||||
} else {
|
||||
root.itemHref = result.data.download_url;
|
||||
root.isWearable = result.data.categories.indexOf("Wearables") > -1;
|
||||
root.activeView = "checkoutSuccess";
|
||||
}
|
||||
}
|
||||
|
@ -239,6 +241,25 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HifiCommerceCommon.FirstUseTutorial {
|
||||
id: firstUseTutorial;
|
||||
z: 999;
|
||||
visible: root.activeView === "firstUseTutorial";
|
||||
anchors.fill: parent;
|
||||
|
||||
Connections {
|
||||
onSendSignalToParent: {
|
||||
switch (message.method) {
|
||||
case 'tutorial_skipClicked':
|
||||
case 'tutorial_finished':
|
||||
Settings.setValue("isFirstUseOfPurchases", false);
|
||||
root.activeView = "checkoutSuccess";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -573,7 +594,7 @@ Rectangle {
|
|||
height: 50;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
text: "Rez It"
|
||||
text: root.isWearable ? "Wear It" : "Rez It"
|
||||
onClicked: {
|
||||
if (urlHandler.canHandleUrl(root.itemHref)) {
|
||||
urlHandler.handleUrl(root.itemHref);
|
||||
|
@ -584,7 +605,7 @@ Rectangle {
|
|||
}
|
||||
RalewaySemiBold {
|
||||
id: noPermissionText;
|
||||
visible: !root.canRezCertifiedItems;
|
||||
visible: !root.canRezCertifiedItems && !root.isWearable;
|
||||
text: '<font color="' + hifi.colors.redAccent + '"><a href="#">You do not have Certified Rez permissions in this domain.</a></font>'
|
||||
// Text size
|
||||
size: 16;
|
||||
|
@ -611,6 +632,28 @@ Rectangle {
|
|||
lightboxPopup.visible = true;
|
||||
}
|
||||
}
|
||||
RalewaySemiBold {
|
||||
id: explainRezText;
|
||||
//visible: !root.isWearable;
|
||||
text: '<font color="' + hifi.colors.redAccent + '"><a href="#">What does "Rez" mean?</a></font>'
|
||||
// Text size
|
||||
size: 16;
|
||||
// Anchors
|
||||
anchors.top: noPermissionText.visible ? noPermissionText.bottom : rezNowButton.bottom;
|
||||
anchors.topMargin: 6;
|
||||
height: paintedHeight;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
// Style
|
||||
color: hifi.colors.redAccent;
|
||||
wrapMode: Text.WordWrap;
|
||||
// Alignment
|
||||
horizontalAlignment: Text.AlignHCenter;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
onLinkActivated: {
|
||||
root.activeView = "firstUseTutorial";
|
||||
}
|
||||
}
|
||||
|
||||
RalewaySemiBold {
|
||||
id: myPurchasesLink;
|
||||
|
@ -618,7 +661,7 @@ Rectangle {
|
|||
// Text size
|
||||
size: 20;
|
||||
// Anchors
|
||||
anchors.top: noPermissionText.visible ? noPermissionText.bottom : rezNowButton.bottom;
|
||||
anchors.top: explainRezText.visible ? explainRezText.bottom : (noPermissionText.visible ? noPermissionText.bottom : rezNowButton.bottom);
|
||||
anchors.topMargin: 40;
|
||||
height: paintedHeight;
|
||||
anchors.left: parent.left;
|
||||
|
|
|
@ -25,7 +25,13 @@ Rectangle {
|
|||
HifiConstants { id: hifi; }
|
||||
|
||||
id: root;
|
||||
property int activeView: 1;
|
||||
property int activeView: 1;
|
||||
|
||||
onVisibleChanged: {
|
||||
if (visible) {
|
||||
root.activeView = 1;
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
anchors.fill: parent;
|
Before ![]() (image error) Size: 72 KiB After ![]() (image error) Size: 72 KiB ![]() ![]() |
Before ![]() (image error) Size: 81 KiB After ![]() (image error) Size: 81 KiB ![]() ![]() |
|
@ -200,12 +200,6 @@ Rectangle {
|
|||
// Style
|
||||
color: hifi.colors.lightGray;
|
||||
}
|
||||
FontLoader { id: ralewayRegular; source: "../../../../fonts/Raleway-Regular.ttf"; }
|
||||
TextMetrics {
|
||||
id: textMetrics;
|
||||
font.family: ralewayRegular.name
|
||||
text: root.itemOwner;
|
||||
}
|
||||
RalewayRegular {
|
||||
id: ownedBy;
|
||||
text: root.itemOwner;
|
||||
|
@ -215,8 +209,7 @@ Rectangle {
|
|||
anchors.top: ownedByHeader.bottom;
|
||||
anchors.topMargin: 8;
|
||||
anchors.left: ownedByHeader.left;
|
||||
height: textMetrics.height;
|
||||
width: root.isMyCert ? textMetrics.width + 25 : ownedByHeader.width;
|
||||
height: paintedHeight;
|
||||
// Style
|
||||
color: hifi.colors.darkGray;
|
||||
elide: Text.ElideRight;
|
||||
|
@ -231,7 +224,7 @@ Rectangle {
|
|||
anchors.topMargin: 4;
|
||||
anchors.bottom: ownedBy.bottom;
|
||||
anchors.left: ownedBy.right;
|
||||
anchors.leftMargin: 4;
|
||||
anchors.leftMargin: 6;
|
||||
anchors.right: ownedByHeader.right;
|
||||
// Style
|
||||
color: hifi.colors.lightGray;
|
||||
|
|
|
@ -39,6 +39,7 @@ Item {
|
|||
property int itemEdition;
|
||||
property int numberSold;
|
||||
property int limitedRun;
|
||||
property bool isWearable;
|
||||
|
||||
property string originalStatusText;
|
||||
property string originalStatusColor;
|
||||
|
@ -342,7 +343,7 @@ Item {
|
|||
anchors.bottom: parent.bottom;
|
||||
anchors.right: parent.right;
|
||||
width: height;
|
||||
enabled: root.canRezCertifiedItems && root.purchaseStatus !== "invalidated";
|
||||
enabled: (root.canRezCertifiedItems || root.isWearable) && root.purchaseStatus !== "invalidated";
|
||||
|
||||
onClicked: {
|
||||
if (urlHandler.canHandleUrl(root.itemHref)) {
|
||||
|
@ -415,7 +416,7 @@ Item {
|
|||
size: 16;
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: "Rez It"
|
||||
text: root.isWearable ? "Wear It" : "Rez It"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ Rectangle {
|
|||
property bool securityImageResultReceived: false;
|
||||
property bool purchasesReceived: false;
|
||||
property bool punctuationMode: false;
|
||||
property bool canRezCertifiedItems: Entities.canRezCertified || Entities.canRezTmpCertified;
|
||||
property bool canRezCertifiedItems: Entities.canRezCertified() || Entities.canRezTmpCertified();
|
||||
property bool pendingInventoryReply: true;
|
||||
property bool isShowingMyItems: false;
|
||||
property bool isDebuggingFirstUseTutorial: false;
|
||||
|
@ -241,7 +241,7 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
|
||||
FirstUseTutorial {
|
||||
HifiCommerceCommon.FirstUseTutorial {
|
||||
id: firstUseTutorial;
|
||||
z: 999;
|
||||
visible: root.activeView === "firstUseTutorial";
|
||||
|
@ -434,6 +434,7 @@ Rectangle {
|
|||
numberSold: model.number_sold;
|
||||
limitedRun: model.limited_run;
|
||||
displayedItemCount: model.displayedItemCount;
|
||||
isWearable: model.categories.indexOf("Wearables") > -1;
|
||||
anchors.topMargin: 12;
|
||||
anchors.bottomMargin: 12;
|
||||
|
||||
|
@ -582,9 +583,11 @@ Rectangle {
|
|||
|
||||
Timer {
|
||||
id: inventoryTimer;
|
||||
interval: 90000;
|
||||
interval: 4000; // Change this back to 90000 after demo
|
||||
//interval: 90000;
|
||||
onTriggered: {
|
||||
if (root.activeView === "purchasesMain" && !root.pendingInventoryReply) {
|
||||
console.log("Refreshing Purchases...");
|
||||
root.pendingInventoryReply = true;
|
||||
commerce.inventory();
|
||||
}
|
||||
|
@ -660,6 +663,8 @@ Rectangle {
|
|||
currentPurchasesModelStatus !== previousPurchasesModelStatus) {
|
||||
|
||||
purchasesModel.setProperty(i, "statusChanged", true);
|
||||
} else {
|
||||
purchasesModel.setProperty(i, "statusChanged", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ Item {
|
|||
|
||||
id: root;
|
||||
property string keyFilePath;
|
||||
property bool showDebugButtons: true;
|
||||
|
||||
Hifi.QmlCommerce {
|
||||
id: commerce;
|
||||
|
@ -56,6 +57,7 @@ Item {
|
|||
}
|
||||
HifiControlsUit.Button {
|
||||
id: clearCachedPassphraseButton;
|
||||
visible: root.showDebugButtons;
|
||||
color: hifi.buttons.black;
|
||||
colorScheme: hifi.colorSchemes.dark;
|
||||
anchors.top: parent.top;
|
||||
|
@ -71,6 +73,7 @@ Item {
|
|||
}
|
||||
HifiControlsUit.Button {
|
||||
id: resetButton;
|
||||
visible: root.showDebugButtons;
|
||||
color: hifi.buttons.red;
|
||||
colorScheme: hifi.colorSchemes.dark;
|
||||
anchors.top: clearCachedPassphraseButton.top;
|
||||
|
@ -90,17 +93,22 @@ Item {
|
|||
ListElement {
|
||||
isExpanded: false;
|
||||
question: "What are private keys?"
|
||||
answer: qsTr("A private key is a secret piece of text that is used to decrypt code.<br><br>In High Fidelity, <b>your private keys are used to decrypt the contents of your Wallet and Purchases.</b>");
|
||||
answer: qsTr("A private key is a secret piece of text that is used to prove ownership, unlock confidential information, and sign transactions.<br><br>In High Fidelity, <b>your private keys are used to securely access the contents of your Wallet and Purchases.</b>");
|
||||
}
|
||||
ListElement {
|
||||
isExpanded: false;
|
||||
question: "Where are my private keys stored?"
|
||||
answer: qsTr('Your private keys are <b>only stored on your hard drive</b> in High Fidelity Interface\'s AppData directory.<br><br><b><font color="#0093C5"><a href="#privateKeyPath">Tap here to open the file path of your hifikey in your file explorer.</a></font></b><br><br> You may backup this file by copying it to a USB flash drive, or to a service like Dropbox or Google Drive. Restore your backup by replacing the file in Interface\'s AppData directory with your backed-up copy.');
|
||||
answer: qsTr('By default, your private keys are <b>only stored on your hard drive</b> in High Fidelity Interface\'s AppData directory.<br><br><b><font color="#0093C5"><a href="#privateKeyPath">Tap here to open the folder where your HifiKeys are stored on your main display.</a></font></b>');
|
||||
}
|
||||
ListElement {
|
||||
isExpanded: false;
|
||||
question: "How can I backup my private keys?"
|
||||
answer: qsTr('You may backup the file containing your private keys by copying it to a USB flash drive, or to a service like Dropbox or Google Drive.<br><br>Restore your backup by replacing the file in Interface\'s AppData directory with your backed-up copy.<br><br><b><font color="#0093C5"><a href="#privateKeyPath">Tap here to open the folder where your HifiKeys are stored on your main display.</a></font></b>');
|
||||
}
|
||||
ListElement {
|
||||
isExpanded: false;
|
||||
question: "What happens if I lose my passphrase?"
|
||||
answer: qsTr("If you lose your passphrase, you will no longer have access to the contents of your Wallet or My Purchases.<br><br><b>Nobody can help you recover your passphrase, including High Fidelity.</b> Please write it down and store it securely.");
|
||||
answer: qsTr("Your passphrase is used to encrypt your private keys. If you lose your passphrase, you will no longer be able to decrypt your private key file. You will also no longer have access to the contents of your Wallet or My Purchases.<br><br><b>Nobody can help you recover your passphrase, including High Fidelity.</b> Please write it down and store it securely.");
|
||||
}
|
||||
ListElement {
|
||||
isExpanded: false;
|
||||
|
|
|
@ -25,8 +25,9 @@ Item {
|
|||
HifiConstants { id: hifi; }
|
||||
|
||||
id: root;
|
||||
z: 998;
|
||||
z: 997;
|
||||
property bool keyboardRaised: false;
|
||||
property bool isPasswordField: false;
|
||||
property string titleBarIcon: "";
|
||||
property string titleBarText: "";
|
||||
|
||||
|
@ -202,6 +203,7 @@ Item {
|
|||
|
||||
onFocusChanged: {
|
||||
root.keyboardRaised = focus;
|
||||
root.isPasswordField = (focus && passphraseField.echoMode === TextInput.Password);
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
|
@ -209,6 +211,7 @@ Item {
|
|||
|
||||
onClicked: {
|
||||
root.keyboardRaised = true;
|
||||
root.isPasswordField = (passphraseField.echoMode === TextInput.Password);
|
||||
mouse.accepted = false;
|
||||
}
|
||||
}
|
||||
|
@ -350,7 +353,7 @@ Item {
|
|||
|
||||
Item {
|
||||
id: keyboardContainer;
|
||||
z: 999;
|
||||
z: 998;
|
||||
visible: keyboard.raised;
|
||||
property bool punctuationMode: false;
|
||||
anchors {
|
||||
|
@ -361,11 +364,13 @@ Item {
|
|||
|
||||
Image {
|
||||
id: lowerKeyboardButton;
|
||||
z: 999;
|
||||
source: "images/lowerKeyboard.png";
|
||||
anchors.horizontalCenter: parent.horizontalCenter;
|
||||
anchors.bottom: keyboard.top;
|
||||
height: 30;
|
||||
width: 120;
|
||||
anchors.right: keyboard.right;
|
||||
anchors.top: keyboard.showMirrorText ? keyboard.top : undefined;
|
||||
anchors.bottom: keyboard.showMirrorText ? undefined : keyboard.bottom;
|
||||
height: 50;
|
||||
width: 60;
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent;
|
||||
|
@ -380,6 +385,7 @@ Item {
|
|||
id: keyboard;
|
||||
raised: HMD.mounted && root.keyboardRaised;
|
||||
numeric: parent.punctuationMode;
|
||||
password: root.isPasswordField;
|
||||
anchors {
|
||||
bottom: parent.bottom;
|
||||
left: parent.left;
|
||||
|
|
|
@ -80,16 +80,18 @@ Item {
|
|||
|
||||
onFocusChanged: {
|
||||
if (focus) {
|
||||
sendSignalToWallet({method: 'walletSetup_raiseKeyboard'});
|
||||
var hidePassword = (currentPassphraseField.echoMode === TextInput.Password);
|
||||
sendSignalToWallet({method: 'walletSetup_raiseKeyboard', isPasswordField: hidePassword});
|
||||
} else if (!passphraseFieldAgain.focus) {
|
||||
sendSignalToWallet({method: 'walletSetup_lowerKeyboard'});
|
||||
sendSignalToWallet({method: 'walletSetup_lowerKeyboard', isPasswordField: false});
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent;
|
||||
onPressed: {
|
||||
sendSignalToWallet({method: 'walletSetup_raiseKeyboard'});
|
||||
var hidePassword = (currentPassphraseField.echoMode === TextInput.Password);
|
||||
sendSignalToWallet({method: 'walletSetup_raiseKeyboard', isPasswordField: hidePassword});
|
||||
mouse.accepted = false;
|
||||
}
|
||||
}
|
||||
|
@ -116,16 +118,18 @@ Item {
|
|||
MouseArea {
|
||||
anchors.fill: parent;
|
||||
onPressed: {
|
||||
sendSignalToWallet({method: 'walletSetup_raiseKeyboard'});
|
||||
var hidePassword = (passphraseField.echoMode === TextInput.Password);
|
||||
sendSignalToWallet({method: 'walletSetup_raiseKeyboard', isPasswordField: hidePassword});
|
||||
mouse.accepted = false;
|
||||
}
|
||||
}
|
||||
|
||||
onFocusChanged: {
|
||||
if (focus) {
|
||||
sendMessageToLightbox({method: 'walletSetup_raiseKeyboard'});
|
||||
var hidePassword = (passphraseField.echoMode === TextInput.Password);
|
||||
sendMessageToLightbox({method: 'walletSetup_raiseKeyboard', isPasswordField: hidePassword});
|
||||
} else if (!passphraseFieldAgain.focus) {
|
||||
sendMessageToLightbox({method: 'walletSetup_lowerKeyboard'});
|
||||
sendMessageToLightbox({method: 'walletSetup_lowerKeyboard', isPasswordField: false});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,16 +154,18 @@ Item {
|
|||
MouseArea {
|
||||
anchors.fill: parent;
|
||||
onPressed: {
|
||||
sendSignalToWallet({method: 'walletSetup_raiseKeyboard'});
|
||||
var hidePassword = (passphraseFieldAgain.echoMode === TextInput.Password);
|
||||
sendSignalToWallet({method: 'walletSetup_raiseKeyboard', isPasswordField: hidePassword});
|
||||
mouse.accepted = false;
|
||||
}
|
||||
}
|
||||
|
||||
onFocusChanged: {
|
||||
if (focus) {
|
||||
sendMessageToLightbox({method: 'walletSetup_raiseKeyboard'});
|
||||
var hidePassword = (passphraseFieldAgain.echoMode === TextInput.Password);
|
||||
sendMessageToLightbox({method: 'walletSetup_raiseKeyboard', isPasswordField: hidePassword});
|
||||
} else if (!passphraseField.focus) {
|
||||
sendMessageToLightbox({method: 'walletSetup_lowerKeyboard'});
|
||||
sendMessageToLightbox({method: 'walletSetup_lowerKeyboard', isPasswordField: false});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -290,7 +290,17 @@ Item {
|
|||
id: removeHmdContainer;
|
||||
z: 998;
|
||||
visible: false;
|
||||
color: hifi.colors.blueHighlight;
|
||||
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0.2;
|
||||
color: hifi.colors.baseGrayHighlight;
|
||||
}
|
||||
GradientStop {
|
||||
position: 1.0;
|
||||
color: hifi.colors.baseGrayShadow;
|
||||
}
|
||||
}
|
||||
anchors.fill: backupInstructionsButton;
|
||||
radius: 5;
|
||||
MouseArea {
|
||||
|
|
|
@ -29,6 +29,7 @@ Rectangle {
|
|||
|
||||
property string activeView: "initialize";
|
||||
property bool keyboardRaised: false;
|
||||
property bool isPassword: false;
|
||||
|
||||
Image {
|
||||
anchors.fill: parent;
|
||||
|
@ -165,7 +166,7 @@ Rectangle {
|
|||
WalletSetup {
|
||||
id: walletSetup;
|
||||
visible: root.activeView === "walletSetup";
|
||||
z: 998;
|
||||
z: 997;
|
||||
anchors.fill: parent;
|
||||
|
||||
Connections {
|
||||
|
@ -181,8 +182,10 @@ Rectangle {
|
|||
}
|
||||
} else if (msg.method === 'walletSetup_raiseKeyboard') {
|
||||
root.keyboardRaised = true;
|
||||
root.isPassword = msg.isPasswordField;
|
||||
} else if (msg.method === 'walletSetup_lowerKeyboard') {
|
||||
root.keyboardRaised = false;
|
||||
root.isPassword = msg.isPasswordField;
|
||||
} else {
|
||||
sendToScript(msg);
|
||||
}
|
||||
|
@ -192,7 +195,7 @@ Rectangle {
|
|||
PassphraseChange {
|
||||
id: passphraseChange;
|
||||
visible: root.activeView === "passphraseChange";
|
||||
z: 998;
|
||||
z: 997;
|
||||
anchors.top: titleBarContainer.bottom;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
|
@ -202,6 +205,7 @@ Rectangle {
|
|||
onSendSignalToWallet: {
|
||||
if (msg.method === 'walletSetup_raiseKeyboard') {
|
||||
root.keyboardRaised = true;
|
||||
root.isPassword = msg.isPasswordField;
|
||||
} else if (msg.method === 'walletSetup_lowerKeyboard') {
|
||||
root.keyboardRaised = false;
|
||||
} else if (msg.method === 'walletSecurity_changePassphraseCancelled') {
|
||||
|
@ -217,7 +221,7 @@ Rectangle {
|
|||
SecurityImageChange {
|
||||
id: securityImageChange;
|
||||
visible: root.activeView === "securityImageChange";
|
||||
z: 998;
|
||||
z: 997;
|
||||
anchors.top: titleBarContainer.bottom;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
|
@ -653,7 +657,7 @@ Rectangle {
|
|||
|
||||
Item {
|
||||
id: keyboardContainer;
|
||||
z: 999;
|
||||
z: 998;
|
||||
visible: keyboard.raised;
|
||||
property bool punctuationMode: false;
|
||||
anchors {
|
||||
|
@ -664,11 +668,13 @@ Rectangle {
|
|||
|
||||
Image {
|
||||
id: lowerKeyboardButton;
|
||||
z: 999;
|
||||
source: "images/lowerKeyboard.png";
|
||||
anchors.horizontalCenter: parent.horizontalCenter;
|
||||
anchors.bottom: keyboard.top;
|
||||
height: 30;
|
||||
width: 120;
|
||||
anchors.right: keyboard.right;
|
||||
anchors.top: keyboard.showMirrorText ? keyboard.top : undefined;
|
||||
anchors.bottom: keyboard.showMirrorText ? undefined : keyboard.bottom;
|
||||
height: 50;
|
||||
width: 60;
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent;
|
||||
|
@ -683,6 +689,7 @@ Rectangle {
|
|||
id: keyboard;
|
||||
raised: HMD.mounted && root.keyboardRaised;
|
||||
numeric: parent.punctuationMode;
|
||||
password: root.isPassword;
|
||||
anchors {
|
||||
bottom: parent.bottom;
|
||||
left: parent.left;
|
||||
|
|
|
@ -43,6 +43,7 @@ Item {
|
|||
|
||||
calculatePendingAndInvalidated();
|
||||
}
|
||||
refreshTimer.start();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,6 +118,8 @@ Item {
|
|||
historyReceived = false;
|
||||
commerce.balance();
|
||||
commerce.history();
|
||||
} else {
|
||||
refreshTimer.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -138,6 +141,17 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: refreshTimer;
|
||||
interval: 4000; // Remove this after demo?
|
||||
onTriggered: {
|
||||
console.log("Refreshing Wallet Home...");
|
||||
historyReceived = false;
|
||||
commerce.balance();
|
||||
commerce.history();
|
||||
}
|
||||
}
|
||||
|
||||
// Recent Activity
|
||||
Rectangle {
|
||||
id: recentActivityContainer;
|
||||
|
@ -164,7 +178,7 @@ Item {
|
|||
anchors.top: parent.top;
|
||||
anchors.topMargin: 26;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 30;
|
||||
anchors.leftMargin: 20;
|
||||
anchors.right: parent.right;
|
||||
anchors.rightMargin: 30;
|
||||
height: 30;
|
||||
|
|
|
@ -679,7 +679,7 @@ Item {
|
|||
anchors.right: parent.right;
|
||||
anchors.rightMargin: 30;
|
||||
height: 40;
|
||||
text: "Open Instructions for Later";
|
||||
text: "Open Backup Instructions for Later";
|
||||
onClicked: {
|
||||
instructions01Container.visible = false;
|
||||
instructions02Container.visible = true;
|
||||
|
|
Before ![]() (image error) Size: 721 B After ![]() (image error) Size: 1.2 KiB ![]() ![]() |
|
@ -1,5 +1,6 @@
|
|||
import QtQuick 2.0
|
||||
import QtGraphicalEffects 1.0
|
||||
import TabletScriptingInterface 1.0
|
||||
|
||||
Item {
|
||||
id: newEntityButton
|
||||
|
@ -122,9 +123,11 @@ Item {
|
|||
hoverEnabled: true
|
||||
enabled: true
|
||||
onClicked: {
|
||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
||||
newEntityButton.clicked();
|
||||
}
|
||||
onEntered: {
|
||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
||||
newEntityButton.state = "hover state";
|
||||
}
|
||||
onExited: {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import QtQuick 2.0
|
||||
import QtGraphicalEffects 1.0
|
||||
import TabletScriptingInterface 1.0
|
||||
|
||||
Item {
|
||||
id: tabletButton
|
||||
|
@ -130,11 +131,13 @@ Item {
|
|||
}
|
||||
tabletButton.clicked();
|
||||
if (tabletRoot) {
|
||||
tabletRoot.playButtonClickSound();
|
||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
||||
}
|
||||
}
|
||||
onEntered: {
|
||||
tabletButton.isEntered = true;
|
||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
||||
|
||||
if (tabletButton.isActive) {
|
||||
tabletButton.state = "hover active state";
|
||||
} else {
|
||||
|
|
|
@ -9,9 +9,13 @@
|
|||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import TabletScriptingInterface 1.0
|
||||
|
||||
import "../../styles-uit"
|
||||
import "."
|
||||
|
||||
FocusScope {
|
||||
id: root
|
||||
implicitHeight: background.height
|
||||
|
@ -69,12 +73,17 @@ FocusScope {
|
|||
onImplicitWidthChanged: listView !== null ? listView.recalcSize() : 0
|
||||
|
||||
MouseArea {
|
||||
enabled: name !== "" && item.enabled
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onEntered: listView.currentIndex = index
|
||||
onEntered: {
|
||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
||||
listView.currentIndex = index
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
root.selected(item)
|
||||
tabletRoot.playButtonClickSound();
|
||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
||||
root.selected(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import QtQuick 2.0
|
||||
import Hifi 1.0
|
||||
import QtQuick.Controls 1.4
|
||||
|
||||
import "../../dialogs"
|
||||
import "../../controls"
|
||||
|
||||
|
|
|
@ -126,7 +126,7 @@ Window {
|
|||
|
||||
sortButtons();
|
||||
|
||||
shown = true;
|
||||
fadeIn(null);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ Window {
|
|||
buttons.splice(index, 1);
|
||||
|
||||
if (buttons.length === 0) {
|
||||
shown = false;
|
||||
fadeOut(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ FocusScope {
|
|||
property var completionCallback;
|
||||
// The target property to animate, usually scale or opacity
|
||||
property alias fadeTargetProperty: root.opacity
|
||||
property bool disableFade: false
|
||||
// always start the property at 0 to enable fade in on creation
|
||||
fadeTargetProperty: 0
|
||||
// DO NOT set visible to false or when derived types override it it
|
||||
|
|
BIN
interface/resources/sounds/Button01.wav
Normal file
BIN
interface/resources/sounds/Button02.wav
Normal file
BIN
interface/resources/sounds/Button03.wav
Normal file
BIN
interface/resources/sounds/Button04.wav
Normal file
BIN
interface/resources/sounds/Button05.wav
Normal file
BIN
interface/resources/sounds/Button06.wav
Normal file
BIN
interface/resources/sounds/Button07.wav
Normal file
BIN
interface/resources/sounds/Collapse.wav
Normal file
BIN
interface/resources/sounds/Expand.wav
Normal file
BIN
interface/resources/sounds/Tab01.wav
Normal file
BIN
interface/resources/sounds/Tab02.wav
Normal file
BIN
interface/resources/sounds/Tab03.wav
Normal file
|
@ -120,6 +120,7 @@
|
|||
#include <SceneScriptingInterface.h>
|
||||
#include <ScriptEngines.h>
|
||||
#include <ScriptCache.h>
|
||||
#include <ShapeEntityItem.h>
|
||||
#include <SoundCache.h>
|
||||
#include <ui/TabletScriptingInterface.h>
|
||||
#include <ui/ToolbarScriptingInterface.h>
|
||||
|
@ -207,6 +208,17 @@
|
|||
#if defined(Q_OS_WIN)
|
||||
#include <VersionHelpers.h>
|
||||
|
||||
#ifdef DEBUG_EVENT_QUEUE
|
||||
// This is a HACK that uses private headers included with the qt source distrubution.
|
||||
// To use this feature you need to add these directores to your include path:
|
||||
// E:/Qt/5.9.1/Src/qtbase/include/QtCore/5.9.1/QtCore
|
||||
// E:/Qt/5.9.1/Src/qtbase/include/QtCore/5.9.1
|
||||
#define QT_BOOTSTRAPPED
|
||||
#include <private/qthread_p.h>
|
||||
#include <private/qobject_p.h>
|
||||
#undef QT_BOOTSTRAPPED
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
_declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
|
||||
}
|
||||
|
@ -264,9 +276,7 @@ private:
|
|||
switch ((int)event->type()) {
|
||||
case ApplicationEvent::Render:
|
||||
render();
|
||||
// Ensure we never back up the render events. Each render should be triggered only in response
|
||||
// to the NEXT render event after the last render occured
|
||||
QCoreApplication::removePostedEvents(this, ApplicationEvent::Render);
|
||||
qApp->_pendingRenderEvent.store(false);
|
||||
return true;
|
||||
|
||||
default:
|
||||
|
@ -1806,6 +1816,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
_rayPickManager.setPrecisionPicking(rayPickID, value);
|
||||
});
|
||||
|
||||
// Preload Tablet sounds
|
||||
DependencyManager::get<TabletScriptingInterface>()->preloadSounds();
|
||||
|
||||
qCDebug(interfaceapp) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(accountManager->getSessionID());
|
||||
}
|
||||
|
||||
|
@ -2214,7 +2227,7 @@ void Application::initializeUi() {
|
|||
offscreenUi->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/"));
|
||||
// OffscreenUi is a subclass of OffscreenQmlSurface specifically designed to
|
||||
// support the window management and scripting proxies for VR use
|
||||
offscreenUi->createDesktop(QString("hifi/Desktop.qml"));
|
||||
offscreenUi->createDesktop(QString("qrc:///qml/hifi/Desktop.qml"));
|
||||
|
||||
// FIXME either expose so that dialogs can set this themselves or
|
||||
// do better detection in the offscreen UI of what has focus
|
||||
|
@ -2283,6 +2296,8 @@ void Application::initializeUi() {
|
|||
|
||||
surfaceContext->setContextProperty("Account", AccountScriptingInterface::getInstance());
|
||||
surfaceContext->setContextProperty("Tablet", DependencyManager::get<TabletScriptingInterface>().data());
|
||||
// Tablet inteference with Tablet.qml. Need to avoid this in QML space
|
||||
surfaceContext->setContextProperty("tabletInterface", DependencyManager::get<TabletScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("DialogsManager", _dialogsManagerScriptingInterface);
|
||||
surfaceContext->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance());
|
||||
surfaceContext->setContextProperty("FaceTracker", DependencyManager::get<DdeFaceTracker>().data());
|
||||
|
@ -2351,8 +2366,8 @@ void Application::initializeUi() {
|
|||
}
|
||||
|
||||
void Application::updateCamera(RenderArgs& renderArgs) {
|
||||
PROFILE_RANGE(render, "/updateCamera");
|
||||
PerformanceTimer perfTimer("CameraUpdates");
|
||||
PROFILE_RANGE(render, __FUNCTION__);
|
||||
PerformanceTimer perfTimer("updateCamera");
|
||||
|
||||
glm::vec3 boomOffset;
|
||||
auto myAvatar = getMyAvatar();
|
||||
|
@ -2568,7 +2583,7 @@ void Application::resizeGL() {
|
|||
}
|
||||
|
||||
void Application::handleSandboxStatus(QNetworkReply* reply) {
|
||||
PROFILE_RANGE(render, "HandleSandboxStatus");
|
||||
PROFILE_RANGE(render, __FUNCTION__);
|
||||
|
||||
bool sandboxIsRunning = SandboxUtils::readStatus(reply->readAll());
|
||||
qDebug() << "HandleSandboxStatus" << sandboxIsRunning;
|
||||
|
@ -2680,9 +2695,14 @@ bool Application::importFromZIP(const QString& filePath) {
|
|||
return true;
|
||||
}
|
||||
|
||||
// thread-safe
|
||||
void Application::onPresent(quint32 frameCount) {
|
||||
postEvent(this, new QEvent((QEvent::Type)ApplicationEvent::Idle), Qt::HighEventPriority);
|
||||
if (_renderEventHandler && !isAboutToQuit()) {
|
||||
bool expected = false;
|
||||
if (_pendingIdleEvent.compare_exchange_strong(expected, true)) {
|
||||
postEvent(this, new QEvent((QEvent::Type)ApplicationEvent::Idle), Qt::HighEventPriority);
|
||||
}
|
||||
expected = false;
|
||||
if (_renderEventHandler && !isAboutToQuit() && _pendingRenderEvent.compare_exchange_strong(expected, true)) {
|
||||
postEvent(_renderEventHandler, new QEvent((QEvent::Type)ApplicationEvent::Render));
|
||||
}
|
||||
}
|
||||
|
@ -2749,7 +2769,26 @@ bool Application::handleFileOpenEvent(QFileOpenEvent* fileEvent) {
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_EVENT_QUEUE
|
||||
static int getEventQueueSize(QThread* thread) {
|
||||
auto threadData = QThreadData::get2(thread);
|
||||
QMutexLocker locker(&threadData->postEventList.mutex);
|
||||
return threadData->postEventList.size();
|
||||
}
|
||||
|
||||
static void dumpEventQueue(QThread* thread) {
|
||||
auto threadData = QThreadData::get2(thread);
|
||||
QMutexLocker locker(&threadData->postEventList.mutex);
|
||||
qDebug() << "AJT: event list, size =" << threadData->postEventList.size();
|
||||
for (auto& postEvent : threadData->postEventList) {
|
||||
QEvent::Type type = (postEvent.event ? postEvent.event->type() : QEvent::None);
|
||||
qDebug() << "AJT: " << type;
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_EVENT_QUEUE
|
||||
|
||||
bool Application::event(QEvent* event) {
|
||||
|
||||
if (!Menu::getInstance()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -2769,8 +2808,18 @@ bool Application::event(QEvent* event) {
|
|||
// see (windowMinimizedChanged)
|
||||
case ApplicationEvent::Idle:
|
||||
idle();
|
||||
// Don't process extra idle events that arrived in the event queue while we were doing this idle
|
||||
QCoreApplication::removePostedEvents(this, ApplicationEvent::Idle);
|
||||
|
||||
#ifdef DEBUG_EVENT_QUEUE
|
||||
{
|
||||
int count = getEventQueueSize(QThread::currentThread());
|
||||
if (count > 400) {
|
||||
dumpEventQueue(QThread::currentThread());
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_EVENT_QUEUE
|
||||
|
||||
_pendingIdleEvent.store(false);
|
||||
|
||||
return true;
|
||||
|
||||
case QEvent::MouseMove:
|
||||
|
@ -4148,6 +4197,10 @@ void Application::init() {
|
|||
// fire off an immediate domain-server check in now that settings are loaded
|
||||
DependencyManager::get<NodeList>()->sendDomainServerCheckIn();
|
||||
|
||||
// This allows collision to be set up properly for shape entities supported by GeometryCache.
|
||||
// This is before entity setup to ensure that it's ready for whenever instance collision is initialized.
|
||||
ShapeEntityItem::setShapeInfoCalulator(ShapeEntityItem::ShapeInfoCalculator(&shapeInfoCalculator));
|
||||
|
||||
getEntities()->init();
|
||||
getEntities()->setEntityLoadingPriorityFunction([this](const EntityItem& item) {
|
||||
auto dims = item.getDimensions();
|
||||
|
@ -4558,7 +4611,6 @@ void Application::updateDialogs(float deltaTime) const {
|
|||
static bool domainLoadingInProgress = false;
|
||||
|
||||
void Application::update(float deltaTime) {
|
||||
|
||||
PROFILE_RANGE_EX(app, __FUNCTION__, 0xffff0000, (uint64_t)_renderFrameCount + 1);
|
||||
|
||||
if (!_physicsEnabled) {
|
||||
|
@ -4753,11 +4805,11 @@ void Application::update(float deltaTime) {
|
|||
QSharedPointer<AvatarManager> avatarManager = DependencyManager::get<AvatarManager>();
|
||||
|
||||
{
|
||||
PROFILE_RANGE_EX(simulation_physics, "Physics", 0xffff0000, (uint64_t)getActiveDisplayPlugin()->presentCount());
|
||||
PROFILE_RANGE(simulation_physics, "Physics");
|
||||
PerformanceTimer perfTimer("physics");
|
||||
if (_physicsEnabled) {
|
||||
{
|
||||
PROFILE_RANGE_EX(simulation_physics, "UpdateStates", 0xffffff00, (uint64_t)getActiveDisplayPlugin()->presentCount());
|
||||
PROFILE_RANGE(simulation_physics, "PreStep");
|
||||
|
||||
PerformanceTimer perfTimer("updateStates)");
|
||||
static VectorOfMotionStates motionStates;
|
||||
|
@ -4791,14 +4843,14 @@ void Application::update(float deltaTime) {
|
|||
});
|
||||
}
|
||||
{
|
||||
PROFILE_RANGE_EX(simulation_physics, "StepSimulation", 0xffff8000, (uint64_t)getActiveDisplayPlugin()->presentCount());
|
||||
PROFILE_RANGE(simulation_physics, "Step");
|
||||
PerformanceTimer perfTimer("stepSimulation");
|
||||
getEntities()->getTree()->withWriteLock([&] {
|
||||
_physicsEngine->stepSimulation();
|
||||
});
|
||||
}
|
||||
{
|
||||
PROFILE_RANGE_EX(simulation_physics, "HarvestChanges", 0xffffff00, (uint64_t)getActiveDisplayPlugin()->presentCount());
|
||||
PROFILE_RANGE(simulation_physics, "PostStep");
|
||||
PerformanceTimer perfTimer("harvestChanges");
|
||||
if (_physicsEngine->hasOutgoingChanges()) {
|
||||
// grab the collision events BEFORE handleOutgoingChanges() because at this point
|
||||
|
@ -4806,6 +4858,7 @@ void Application::update(float deltaTime) {
|
|||
auto& collisionEvents = _physicsEngine->getCollisionEvents();
|
||||
|
||||
getEntities()->getTree()->withWriteLock([&] {
|
||||
PROFILE_RANGE(simulation_physics, "Harvest");
|
||||
PerformanceTimer perfTimer("handleOutgoingChanges");
|
||||
|
||||
const VectorOfMotionStates& outgoingChanges = _physicsEngine->getChangedMotionStates();
|
||||
|
@ -4818,18 +4871,25 @@ void Application::update(float deltaTime) {
|
|||
|
||||
if (!_aboutToQuit) {
|
||||
// handleCollisionEvents() AFTER handleOutgoinChanges()
|
||||
PerformanceTimer perfTimer("entities");
|
||||
avatarManager->handleCollisionEvents(collisionEvents);
|
||||
// Collision events (and their scripts) must not be handled when we're locked, above. (That would risk
|
||||
// deadlock.)
|
||||
_entitySimulation->handleCollisionEvents(collisionEvents);
|
||||
{
|
||||
PROFILE_RANGE(simulation_physics, "CollisionEvents");
|
||||
PerformanceTimer perfTimer("entities");
|
||||
avatarManager->handleCollisionEvents(collisionEvents);
|
||||
// Collision events (and their scripts) must not be handled when we're locked, above. (That would risk
|
||||
// deadlock.)
|
||||
_entitySimulation->handleCollisionEvents(collisionEvents);
|
||||
}
|
||||
|
||||
PROFILE_RANGE(simulation_physics, "UpdateEntities");
|
||||
// NOTE: the getEntities()->update() call below will wait for lock
|
||||
// and will simulate entity motion (the EntityTree has been given an EntitySimulation).
|
||||
getEntities()->update(true); // update the models...
|
||||
}
|
||||
|
||||
myAvatar->harvestResultsFromPhysicsSimulation(deltaTime);
|
||||
{
|
||||
PROFILE_RANGE(simulation_physics, "MyAvatar");
|
||||
myAvatar->harvestResultsFromPhysicsSimulation(deltaTime);
|
||||
}
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails) &&
|
||||
Menu::getInstance()->isOptionChecked(MenuOption::ExpandPhysicsSimulationTiming)) {
|
||||
|
@ -4848,13 +4908,13 @@ void Application::update(float deltaTime) {
|
|||
// AvatarManager update
|
||||
{
|
||||
{
|
||||
PROFILE_RANGE(simulation, "OtherAvatars");
|
||||
PerformanceTimer perfTimer("otherAvatars");
|
||||
PROFILE_RANGE_EX(simulation, "OtherAvatars", 0xffff00ff, (uint64_t)getActiveDisplayPlugin()->presentCount());
|
||||
avatarManager->updateOtherAvatars(deltaTime);
|
||||
}
|
||||
|
||||
{
|
||||
PROFILE_RANGE_EX(simulation, "MyAvatar", 0xffff00ff, (uint64_t)getActiveDisplayPlugin()->presentCount());
|
||||
PROFILE_RANGE(simulation, "MyAvatar");
|
||||
PerformanceTimer perfTimer("MyAvatar");
|
||||
qApp->updateMyAvatarLookAtPosition();
|
||||
avatarManager->updateMyAvatar(deltaTime);
|
||||
|
@ -4998,6 +5058,7 @@ void Application::update(float deltaTime) {
|
|||
}
|
||||
|
||||
this->updateCamera(appRenderArgs._renderArgs);
|
||||
appRenderArgs._eyeToWorld = _myCamera.getTransform();
|
||||
appRenderArgs._isStereo = false;
|
||||
|
||||
{
|
||||
|
@ -5725,6 +5786,8 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe
|
|||
qScriptRegisterMetaType(scriptEngine.data(), wrapperToScriptValue<TabletProxy>, wrapperFromScriptValue<TabletProxy>);
|
||||
qScriptRegisterMetaType(scriptEngine.data(),
|
||||
wrapperToScriptValue<TabletButtonProxy>, wrapperFromScriptValue<TabletButtonProxy>);
|
||||
// Tablet inteference with Tablet.qml. Need to avoid this in QML space
|
||||
scriptEngine->registerGlobalObject("tabletInterface", DependencyManager::get<TabletScriptingInterface>().data());
|
||||
scriptEngine->registerGlobalObject("Tablet", DependencyManager::get<TabletScriptingInterface>().data());
|
||||
|
||||
auto toolbarScriptingInterface = DependencyManager::get<ToolbarScriptingInterface>().data();
|
||||
|
@ -7166,7 +7229,7 @@ void Application::updateDisplayMode() {
|
|||
_offscreenContext->makeCurrent();
|
||||
getApplicationCompositor().setDisplayPlugin(newDisplayPlugin);
|
||||
_displayPlugin = newDisplayPlugin;
|
||||
connect(_displayPlugin.get(), &DisplayPlugin::presented, this, &Application::onPresent);
|
||||
connect(_displayPlugin.get(), &DisplayPlugin::presented, this, &Application::onPresent, Qt::DirectConnection);
|
||||
auto desktop = offscreenUi->getDesktop();
|
||||
if (desktop) {
|
||||
desktop->setProperty("repositionLocked", wasRepositionLocked);
|
||||
|
|
|
@ -704,5 +704,8 @@ private:
|
|||
LaserPointerManager _laserPointerManager;
|
||||
|
||||
friend class RenderEventHandler;
|
||||
|
||||
std::atomic<bool> _pendingIdleEvent { false };
|
||||
std::atomic<bool> _pendingRenderEvent { false };
|
||||
};
|
||||
#endif // hifi_Application_h
|
||||
|
|
|
@ -72,6 +72,12 @@ void Application::paintGL() {
|
|||
{
|
||||
QMutexLocker viewLocker(&_renderArgsMutex);
|
||||
renderArgs = _appRenderArgs._renderArgs;
|
||||
|
||||
// don't render if there is no context.
|
||||
if (!_appRenderArgs._renderArgs._context) {
|
||||
return;
|
||||
}
|
||||
|
||||
HMDSensorPose = _appRenderArgs._headPose;
|
||||
eyeToWorld = _appRenderArgs._eyeToWorld;
|
||||
sensorToWorld = _appRenderArgs._sensorToWorld;
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#include <GeometryCache.h>
|
||||
#include <OctreeConstants.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <ShapeEntityItem.h>
|
||||
#include <ShapeInfo.h>
|
||||
|
||||
#include "InterfaceLogging.h"
|
||||
#include "world.h"
|
||||
|
@ -393,4 +395,20 @@ void runUnitTests() {
|
|||
}
|
||||
}
|
||||
|
||||
void shapeInfoCalculator(const ShapeEntityItem * const shapeEntity, ShapeInfo &shapeInfo) {
|
||||
|
||||
if (shapeEntity == nullptr) {
|
||||
|
||||
//--EARLY EXIT--
|
||||
return;
|
||||
}
|
||||
|
||||
ShapeInfo::PointCollection pointCollection;
|
||||
ShapeInfo::PointList points;
|
||||
pointCollection.push_back(points);
|
||||
|
||||
GeometryCache::computeSimpleHullPointListForShape((int)shapeEntity->getShape(), shapeEntity->getDimensions(), pointCollection.back());
|
||||
shapeInfo.setPointCollection(pointCollection);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
#include <gpu/Batch.h>
|
||||
#include <render/Forward.h>
|
||||
|
||||
class ShapeEntityItem;
|
||||
class ShapeInfo;
|
||||
|
||||
void renderWorldBox(RenderArgs* args, gpu::Batch& batch);
|
||||
|
||||
void runTimingTests();
|
||||
|
@ -28,4 +31,6 @@ bool rayIntersectsSphere(const glm::vec3& rayStarting, const glm::vec3& rayNorma
|
|||
|
||||
bool pointInSphere(glm::vec3& point, glm::vec3& sphereCenter, double sphereRadius);
|
||||
|
||||
void shapeInfoCalculator(const ShapeEntityItem * const shapeEntity, ShapeInfo &shapeInfo);
|
||||
|
||||
#endif // hifi_Util_h
|
||||
|
|
|
@ -587,14 +587,16 @@ void MyAvatar::simulate(float deltaTime) {
|
|||
MovingEntitiesOperator moveOperator;
|
||||
forEachDescendant([&](SpatiallyNestablePointer object) {
|
||||
// if the queryBox has changed, tell the entity-server
|
||||
if (object->getNestableType() == NestableType::Entity && object->checkAndMaybeUpdateQueryAACube()) {
|
||||
if (object->getNestableType() == NestableType::Entity && object->updateQueryAACube()) {
|
||||
EntityItemPointer entity = std::static_pointer_cast<EntityItem>(object);
|
||||
bool success;
|
||||
AACube newCube = entity->getQueryAACube(success);
|
||||
if (success) {
|
||||
moveOperator.addEntityToMoveList(entity, newCube);
|
||||
}
|
||||
if (packetSender) {
|
||||
// send an edit packet to update the entity-server about the queryAABox. If it's an
|
||||
// avatar-entity, don't.
|
||||
if (packetSender && !entity->getClientOnly()) {
|
||||
EntityItemProperties properties = entity->getProperties();
|
||||
properties.setQueryAACubeDirty();
|
||||
properties.setLastEdited(now);
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <QUuid>
|
||||
|
||||
#include <SettingHandle.h>
|
||||
#include <Rig.h>
|
||||
#include <Sound.h>
|
||||
|
@ -106,6 +108,8 @@ class MyAvatar : public Avatar {
|
|||
* "scripts/system/controllers/toggleAdvancedMovementForHandControllers.js".
|
||||
* @property userHeight {number} The height of the user in sensor space. (meters).
|
||||
* @property userEyeHeight {number} Estimated height of the users eyes in sensor space. (meters)
|
||||
* @property SELF_ID {string} READ-ONLY. UUID representing "my avatar". Only use for local-only entities and overlays in situations where MyAvatar.sessionUUID is not available (e.g., if not connected to a domain).
|
||||
* Note: Likely to be deprecated.
|
||||
*/
|
||||
|
||||
// FIXME: `glm::vec3 position` is not accessible from QML, so this exposes position in a QML-native type
|
||||
|
@ -152,6 +156,8 @@ class MyAvatar : public Avatar {
|
|||
|
||||
Q_PROPERTY(float userHeight READ getUserHeight WRITE setUserHeight)
|
||||
Q_PROPERTY(float userEyeHeight READ getUserEyeHeight)
|
||||
|
||||
Q_PROPERTY(QUuid SELF_ID READ getSelfID CONSTANT)
|
||||
|
||||
const QString DOMINANT_LEFT_HAND = "left";
|
||||
const QString DOMINANT_RIGHT_HAND = "right";
|
||||
|
@ -546,6 +552,8 @@ public:
|
|||
|
||||
virtual SpatialParentTree* getParentTree() const override;
|
||||
|
||||
const QUuid& getSelfID() const { return AVATAR_SELF_ID; }
|
||||
|
||||
public slots:
|
||||
void increaseSize();
|
||||
void decreaseSize();
|
||||
|
@ -648,8 +656,6 @@ private:
|
|||
|
||||
void setVisibleInSceneIfReady(Model* model, const render::ScenePointer& scene, bool visiblity);
|
||||
|
||||
private:
|
||||
|
||||
virtual void updatePalms() override {}
|
||||
void lateUpdatePalms();
|
||||
|
||||
|
|
|
@ -105,19 +105,19 @@ RSA* readKeys(const char* filename) {
|
|||
return key;
|
||||
}
|
||||
|
||||
bool writeBackupInstructions() {
|
||||
bool Wallet::writeBackupInstructions() {
|
||||
QString inputFilename(PathUtils::resourcesPath() + "html/commerce/backup_instructions.html");
|
||||
QString filename = PathUtils::getAppDataFilePath(INSTRUCTIONS_FILE);
|
||||
QFile outputFile(filename);
|
||||
QString outputFilename = PathUtils::getAppDataFilePath(INSTRUCTIONS_FILE);
|
||||
QFile outputFile(outputFilename);
|
||||
bool retval = false;
|
||||
|
||||
if (QFile::exists(filename))
|
||||
if (QFile::exists(outputFilename) || getKeyFilePath() == "")
|
||||
{
|
||||
QFile::remove(filename);
|
||||
return false;
|
||||
}
|
||||
QFile::copy(inputFilename, filename);
|
||||
QFile::copy(inputFilename, outputFilename);
|
||||
|
||||
if (QFile::exists(filename) && outputFile.open(QIODevice::ReadWrite)) {
|
||||
if (QFile::exists(outputFilename) && outputFile.open(QIODevice::ReadWrite)) {
|
||||
|
||||
QByteArray fileData = outputFile.readAll();
|
||||
QString text(fileData);
|
||||
|
@ -132,7 +132,7 @@ bool writeBackupInstructions() {
|
|||
retval = true;
|
||||
qCDebug(commerce) << "wrote html file successfully";
|
||||
} else {
|
||||
qCDebug(commerce) << "failed to open output html file" << filename;
|
||||
qCDebug(commerce) << "failed to open output html file" << outputFilename;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
@ -154,8 +154,6 @@ bool writeKeys(const char* filename, RSA* keys) {
|
|||
QFile(QString(filename)).remove();
|
||||
return retval;
|
||||
}
|
||||
|
||||
writeBackupInstructions();
|
||||
|
||||
retval = true;
|
||||
qCDebug(commerce) << "wrote keys successfully";
|
||||
|
@ -359,6 +357,8 @@ bool Wallet::setPassphrase(const QString& passphrase) {
|
|||
|
||||
_publicKeys.clear();
|
||||
|
||||
writeBackupInstructions();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -526,6 +526,8 @@ bool Wallet::generateKeyPair() {
|
|||
qCInfo(commerce) << "Generating keypair.";
|
||||
auto keyPair = generateRSAKeypair();
|
||||
|
||||
writeBackupInstructions();
|
||||
|
||||
// TODO: redo this soon -- need error checking and so on
|
||||
writeSecurityImage(_securityImage, keyFilePath());
|
||||
QString oldKey = _publicKeys.count() == 0 ? "" : _publicKeys.last();
|
||||
|
|
|
@ -80,6 +80,7 @@ private:
|
|||
void updateImageProvider();
|
||||
bool writeSecurityImage(const QPixmap* pixmap, const QString& outputFilePath);
|
||||
bool readSecurityImage(const QString& inputFilePath, unsigned char** outputBufferPtr, int* outputBufferLen);
|
||||
bool writeBackupInstructions();
|
||||
|
||||
bool verifyOwnerChallenge(const QByteArray& encryptedText, const QString& publicKey, QString& decryptedText);
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
//
|
||||
#include "JointRayPick.h"
|
||||
|
||||
#include "DependencyManager.h"
|
||||
#include "avatar/AvatarManager.h"
|
||||
|
||||
JointRayPick::JointRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const RayPickFilter& filter, const float maxDistance, const bool enabled) :
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#ifndef hifi_JointRayPick_h
|
||||
#define hifi_JointRayPick_h
|
||||
|
||||
#include "RayPick.h"
|
||||
#include <pointers/rays/RayPick.h>
|
||||
|
||||
class JointRayPick : public RayPick {
|
||||
|
||||
|
|
|
@ -11,19 +11,21 @@
|
|||
#include "LaserPointer.h"
|
||||
|
||||
#include "Application.h"
|
||||
#include "ui/overlays/Overlay.h"
|
||||
#include "avatar/AvatarManager.h"
|
||||
#include "RayPickScriptingInterface.h"
|
||||
|
||||
LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates,
|
||||
const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) :
|
||||
const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool distanceScaleEnd, const bool enabled) :
|
||||
_renderingEnabled(enabled),
|
||||
_renderStates(renderStates),
|
||||
_defaultRenderStates(defaultRenderStates),
|
||||
_faceAvatar(faceAvatar),
|
||||
_centerEndY(centerEndY),
|
||||
_lockEnd(lockEnd)
|
||||
_lockEnd(lockEnd),
|
||||
_distanceScaleEnd(distanceScaleEnd),
|
||||
_rayPickUID(DependencyManager::get<RayPickScriptingInterface>()->createRayPick(rayProps))
|
||||
{
|
||||
_rayPickUID = DependencyManager::get<RayPickScriptingInterface>()->createRayPick(rayProps);
|
||||
|
||||
|
||||
for (auto& state : _renderStates) {
|
||||
if (!enabled || state.first != _currentRenderState) {
|
||||
|
@ -38,7 +40,7 @@ LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& rende
|
|||
}
|
||||
|
||||
LaserPointer::~LaserPointer() {
|
||||
DependencyManager::get<RayPickScriptingInterface>()->removeRayPick(_rayPickUID);
|
||||
qApp->getRayPickManager().removeRayPick(_rayPickUID);
|
||||
|
||||
for (auto& renderState : _renderStates) {
|
||||
renderState.second.deleteOverlays();
|
||||
|
@ -49,43 +51,51 @@ LaserPointer::~LaserPointer() {
|
|||
}
|
||||
|
||||
void LaserPointer::enable() {
|
||||
QWriteLocker lock(getLock());
|
||||
DependencyManager::get<RayPickScriptingInterface>()->enableRayPick(_rayPickUID);
|
||||
_renderingEnabled = true;
|
||||
qApp->getRayPickManager().enableRayPick(_rayPickUID);
|
||||
withWriteLock([&] {
|
||||
_renderingEnabled = true;
|
||||
});
|
||||
}
|
||||
|
||||
void LaserPointer::disable() {
|
||||
QWriteLocker lock(getLock());
|
||||
DependencyManager::get<RayPickScriptingInterface>()->disableRayPick(_rayPickUID);
|
||||
_renderingEnabled = false;
|
||||
if (!_currentRenderState.empty()) {
|
||||
if (_renderStates.find(_currentRenderState) != _renderStates.end()) {
|
||||
disableRenderState(_renderStates[_currentRenderState]);
|
||||
qApp->getRayPickManager().disableRayPick(_rayPickUID);
|
||||
withWriteLock([&] {
|
||||
_renderingEnabled = false;
|
||||
if (!_currentRenderState.empty()) {
|
||||
if (_renderStates.find(_currentRenderState) != _renderStates.end()) {
|
||||
disableRenderState(_renderStates[_currentRenderState]);
|
||||
}
|
||||
if (_defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) {
|
||||
disableRenderState(_defaultRenderStates[_currentRenderState].second);
|
||||
}
|
||||
}
|
||||
if (_defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) {
|
||||
disableRenderState(_defaultRenderStates[_currentRenderState].second);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void LaserPointer::setRenderState(const std::string& state) {
|
||||
QWriteLocker lock(getLock());
|
||||
if (!_currentRenderState.empty() && state != _currentRenderState) {
|
||||
if (_renderStates.find(_currentRenderState) != _renderStates.end()) {
|
||||
disableRenderState(_renderStates[_currentRenderState]);
|
||||
withWriteLock([&] {
|
||||
if (!_currentRenderState.empty() && state != _currentRenderState) {
|
||||
if (_renderStates.find(_currentRenderState) != _renderStates.end()) {
|
||||
disableRenderState(_renderStates[_currentRenderState]);
|
||||
}
|
||||
if (_defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) {
|
||||
disableRenderState(_defaultRenderStates[_currentRenderState].second);
|
||||
}
|
||||
}
|
||||
if (_defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) {
|
||||
disableRenderState(_defaultRenderStates[_currentRenderState].second);
|
||||
}
|
||||
}
|
||||
_currentRenderState = state;
|
||||
_currentRenderState = state;
|
||||
});
|
||||
}
|
||||
|
||||
void LaserPointer::editRenderState(const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) {
|
||||
QWriteLocker lock(getLock());
|
||||
updateRenderStateOverlay(_renderStates[state].getStartID(), startProps);
|
||||
updateRenderStateOverlay(_renderStates[state].getPathID(), pathProps);
|
||||
updateRenderStateOverlay(_renderStates[state].getEndID(), endProps);
|
||||
withWriteLock([&] {
|
||||
updateRenderStateOverlay(_renderStates[state].getStartID(), startProps);
|
||||
updateRenderStateOverlay(_renderStates[state].getPathID(), pathProps);
|
||||
updateRenderStateOverlay(_renderStates[state].getEndID(), endProps);
|
||||
QVariant endDim = endProps.toMap()["dimensions"];
|
||||
if (endDim.isValid()) {
|
||||
_renderStates[state].setEndDim(vec3FromVariant(endDim));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void LaserPointer::updateRenderStateOverlay(const OverlayID& id, const QVariant& props) {
|
||||
|
@ -97,8 +107,7 @@ void LaserPointer::updateRenderStateOverlay(const OverlayID& id, const QVariant&
|
|||
}
|
||||
|
||||
const RayPickResult LaserPointer::getPrevRayPickResult() {
|
||||
QReadLocker lock(getLock());
|
||||
return DependencyManager::get<RayPickScriptingInterface>()->getPrevRayPickResult(_rayPickUID);
|
||||
return qApp->getRayPickManager().getPrevRayPickResult(_rayPickUID);
|
||||
}
|
||||
|
||||
void LaserPointer::updateRenderState(const RenderState& renderState, const IntersectionType type, const float distance, const QUuid& objectID, const PickRay& pickRay, const bool defaultState) {
|
||||
|
@ -154,10 +163,14 @@ void LaserPointer::updateRenderState(const RenderState& renderState, const Inter
|
|||
if (!renderState.getEndID().isNull()) {
|
||||
QVariantMap endProps;
|
||||
glm::quat faceAvatarRotation = DependencyManager::get<AvatarManager>()->getMyAvatar()->getOrientation() * glm::quat(glm::radians(glm::vec3(0.0f, 180.0f, 0.0f)));
|
||||
glm::vec3 dim = vec3FromVariant(qApp->getOverlays().getProperty(renderState.getEndID(), "dimensions").value);
|
||||
if (_distanceScaleEnd) {
|
||||
dim = renderState.getEndDim() * glm::distance(pickRay.origin, endVec) * DependencyManager::get<AvatarManager>()->getMyAvatar()->getSensorToWorldScale();
|
||||
endProps.insert("dimensions", vec3toVariant(dim));
|
||||
}
|
||||
if (_centerEndY) {
|
||||
endProps.insert("position", end);
|
||||
} else {
|
||||
glm::vec3 dim = vec3FromVariant(qApp->getOverlays().getProperty(renderState.getEndID(), "dimensions").value);
|
||||
glm::vec3 currentUpVector = faceAvatarRotation * Vectors::UP;
|
||||
endProps.insert("position", vec3toVariant(endVec + glm::vec3(currentUpVector.x * 0.5f * dim.y, currentUpVector.y * 0.5f * dim.y, currentUpVector.z * 0.5f * dim.y)));
|
||||
}
|
||||
|
@ -193,65 +206,45 @@ void LaserPointer::disableRenderState(const RenderState& renderState) {
|
|||
|
||||
void LaserPointer::update() {
|
||||
// This only needs to be a read lock because update won't change any of the properties that can be modified from scripts
|
||||
QReadLocker lock(getLock());
|
||||
RayPickResult prevRayPickResult = DependencyManager::get<RayPickScriptingInterface>()->getPrevRayPickResult(_rayPickUID);
|
||||
if (_renderingEnabled && !_currentRenderState.empty() && _renderStates.find(_currentRenderState) != _renderStates.end() &&
|
||||
withReadLock([&] {
|
||||
RayPickResult prevRayPickResult = qApp->getRayPickManager().getPrevRayPickResult(_rayPickUID);
|
||||
if (_renderingEnabled && !_currentRenderState.empty() && _renderStates.find(_currentRenderState) != _renderStates.end() &&
|
||||
(prevRayPickResult.type != IntersectionType::NONE || _laserLength > 0.0f || !_objectLockEnd.first.isNull())) {
|
||||
float distance = _laserLength > 0.0f ? _laserLength : prevRayPickResult.distance;
|
||||
updateRenderState(_renderStates[_currentRenderState], prevRayPickResult.type, distance, prevRayPickResult.objectID, prevRayPickResult.searchRay, false);
|
||||
disableRenderState(_defaultRenderStates[_currentRenderState].second);
|
||||
} else if (_renderingEnabled && !_currentRenderState.empty() && _defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) {
|
||||
disableRenderState(_renderStates[_currentRenderState]);
|
||||
updateRenderState(_defaultRenderStates[_currentRenderState].second, IntersectionType::NONE, _defaultRenderStates[_currentRenderState].first, QUuid(), prevRayPickResult.searchRay, true);
|
||||
} else if (!_currentRenderState.empty()) {
|
||||
disableRenderState(_renderStates[_currentRenderState]);
|
||||
disableRenderState(_defaultRenderStates[_currentRenderState].second);
|
||||
}
|
||||
float distance = _laserLength > 0.0f ? _laserLength : prevRayPickResult.distance;
|
||||
updateRenderState(_renderStates[_currentRenderState], prevRayPickResult.type, distance, prevRayPickResult.objectID, prevRayPickResult.searchRay, false);
|
||||
disableRenderState(_defaultRenderStates[_currentRenderState].second);
|
||||
} else if (_renderingEnabled && !_currentRenderState.empty() && _defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) {
|
||||
disableRenderState(_renderStates[_currentRenderState]);
|
||||
updateRenderState(_defaultRenderStates[_currentRenderState].second, IntersectionType::NONE, _defaultRenderStates[_currentRenderState].first, QUuid(), prevRayPickResult.searchRay, true);
|
||||
} else if (!_currentRenderState.empty()) {
|
||||
disableRenderState(_renderStates[_currentRenderState]);
|
||||
disableRenderState(_defaultRenderStates[_currentRenderState].second);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void LaserPointer::setPrecisionPicking(const bool precisionPicking) {
|
||||
QWriteLocker lock(getLock());
|
||||
DependencyManager::get<RayPickScriptingInterface>()->setPrecisionPicking(_rayPickUID, precisionPicking);
|
||||
qApp->getRayPickManager().setPrecisionPicking(_rayPickUID, precisionPicking);
|
||||
}
|
||||
|
||||
void LaserPointer::setLaserLength(const float laserLength) {
|
||||
QWriteLocker lock(getLock());
|
||||
_laserLength = laserLength;
|
||||
withWriteLock([&] {
|
||||
_laserLength = laserLength;
|
||||
});
|
||||
}
|
||||
|
||||
void LaserPointer::setLockEndUUID(QUuid objectID, const bool isOverlay) {
|
||||
QWriteLocker lock(getLock());
|
||||
_objectLockEnd = std::pair<QUuid, bool>(objectID, isOverlay);
|
||||
withWriteLock([&] {
|
||||
_objectLockEnd = std::pair<QUuid, bool>(objectID, isOverlay);
|
||||
});
|
||||
}
|
||||
|
||||
void LaserPointer::setIgnoreEntities(const QScriptValue& ignoreEntities) {
|
||||
QWriteLocker lock(getLock());
|
||||
DependencyManager::get<RayPickScriptingInterface>()->setIgnoreEntities(_rayPickUID, ignoreEntities);
|
||||
void LaserPointer::setIgnoreItems(const QVector<QUuid>& ignoreItems) const {
|
||||
qApp->getRayPickManager().setIgnoreItems(_rayPickUID, ignoreItems);
|
||||
}
|
||||
|
||||
void LaserPointer::setIncludeEntities(const QScriptValue& includeEntities) {
|
||||
QWriteLocker lock(getLock());
|
||||
DependencyManager::get<RayPickScriptingInterface>()->setIncludeEntities(_rayPickUID, includeEntities);
|
||||
}
|
||||
|
||||
void LaserPointer::setIgnoreOverlays(const QScriptValue& ignoreOverlays) {
|
||||
QWriteLocker lock(getLock());
|
||||
DependencyManager::get<RayPickScriptingInterface>()->setIgnoreOverlays(_rayPickUID, ignoreOverlays);
|
||||
}
|
||||
|
||||
void LaserPointer::setIncludeOverlays(const QScriptValue& includeOverlays) {
|
||||
QWriteLocker lock(getLock());
|
||||
DependencyManager::get<RayPickScriptingInterface>()->setIncludeOverlays(_rayPickUID, includeOverlays);
|
||||
}
|
||||
|
||||
void LaserPointer::setIgnoreAvatars(const QScriptValue& ignoreAvatars) {
|
||||
QWriteLocker lock(getLock());
|
||||
DependencyManager::get<RayPickScriptingInterface>()->setIgnoreAvatars(_rayPickUID, ignoreAvatars);
|
||||
}
|
||||
|
||||
void LaserPointer::setIncludeAvatars(const QScriptValue& includeAvatars) {
|
||||
QWriteLocker lock(getLock());
|
||||
DependencyManager::get<RayPickScriptingInterface>()->setIncludeAvatars(_rayPickUID, includeAvatars);
|
||||
void LaserPointer::setIncludeItems(const QVector<QUuid>& includeItems) const {
|
||||
qApp->getRayPickManager().setIncludeItems(_rayPickUID, includeItems);
|
||||
}
|
||||
|
||||
RenderState::RenderState(const OverlayID& startID, const OverlayID& pathID, const OverlayID& endID) :
|
||||
|
@ -264,6 +257,7 @@ RenderState::RenderState(const OverlayID& startID, const OverlayID& pathID, cons
|
|||
_pathIgnoreRays = qApp->getOverlays().getProperty(_pathID, "ignoreRayIntersection").value.toBool();
|
||||
}
|
||||
if (!_endID.isNull()) {
|
||||
_endDim = vec3FromVariant(qApp->getOverlays().getProperty(_endID, "dimensions").value);
|
||||
_endIgnoreRays = qApp->getOverlays().getProperty(_endID, "ignoreRayIntersection").value.toBool();
|
||||
}
|
||||
}
|
||||
|
@ -278,4 +272,4 @@ void RenderState::deleteOverlays() {
|
|||
if (!_endID.isNull()) {
|
||||
qApp->getOverlays().deleteOverlay(_endID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,10 +12,12 @@
|
|||
#define hifi_LaserPointer_h
|
||||
|
||||
#include <QString>
|
||||
#include "glm/glm.hpp"
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <DependencyManager.h>
|
||||
#include "raypick/RayPickScriptingInterface.h"
|
||||
#include <shared/ReadWriteLockable.h>
|
||||
|
||||
#include "ui/overlays/Overlay.h"
|
||||
|
||||
class RayPickResult;
|
||||
|
||||
|
@ -32,6 +34,9 @@ public:
|
|||
const bool& doesPathIgnoreRays() const { return _pathIgnoreRays; }
|
||||
const bool& doesEndIgnoreRays() const { return _endIgnoreRays; }
|
||||
|
||||
void setEndDim(const glm::vec3& endDim) { _endDim = endDim; }
|
||||
const glm::vec3& getEndDim() const { return _endDim; }
|
||||
|
||||
void deleteOverlays();
|
||||
|
||||
private:
|
||||
|
@ -41,18 +46,21 @@ private:
|
|||
bool _startIgnoreRays;
|
||||
bool _pathIgnoreRays;
|
||||
bool _endIgnoreRays;
|
||||
|
||||
glm::vec3 _endDim;
|
||||
};
|
||||
|
||||
|
||||
class LaserPointer {
|
||||
class LaserPointer : public ReadWriteLockable {
|
||||
|
||||
public:
|
||||
using Pointer = std::shared_ptr<LaserPointer>;
|
||||
|
||||
typedef std::unordered_map<std::string, RenderState> RenderStateMap;
|
||||
typedef std::unordered_map<std::string, std::pair<float, RenderState>> DefaultRenderStateMap;
|
||||
|
||||
LaserPointer(const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates,
|
||||
const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled);
|
||||
const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool distanceScaleEnd, const bool enabled);
|
||||
~LaserPointer();
|
||||
|
||||
QUuid getRayUID() { return _rayPickUID; }
|
||||
|
@ -68,14 +76,8 @@ public:
|
|||
void setLaserLength(const float laserLength);
|
||||
void setLockEndUUID(QUuid objectID, const bool isOverlay);
|
||||
|
||||
void setIgnoreEntities(const QScriptValue& ignoreEntities);
|
||||
void setIncludeEntities(const QScriptValue& includeEntities);
|
||||
void setIgnoreOverlays(const QScriptValue& ignoreOverlays);
|
||||
void setIncludeOverlays(const QScriptValue& includeOverlays);
|
||||
void setIgnoreAvatars(const QScriptValue& ignoreAvatars);
|
||||
void setIncludeAvatars(const QScriptValue& includeAvatars);
|
||||
|
||||
QReadWriteLock* getLock() { return &_lock; }
|
||||
void setIgnoreItems(const QVector<QUuid>& ignoreItems) const;
|
||||
void setIncludeItems(const QVector<QUuid>& includeItems) const;
|
||||
|
||||
void update();
|
||||
|
||||
|
@ -88,10 +90,10 @@ private:
|
|||
bool _faceAvatar;
|
||||
bool _centerEndY;
|
||||
bool _lockEnd;
|
||||
bool _distanceScaleEnd;
|
||||
std::pair<QUuid, bool> _objectLockEnd { std::pair<QUuid, bool>(QUuid(), false)};
|
||||
|
||||
QUuid _rayPickUID;
|
||||
QReadWriteLock _lock;
|
||||
const QUuid _rayPickUID;
|
||||
|
||||
void updateRenderStateOverlay(const OverlayID& id, const QVariant& props);
|
||||
void updateRenderState(const RenderState& renderState, const IntersectionType type, const float distance, const QUuid& objectID, const PickRay& pickRay, const bool defaultState);
|
||||
|
|
|
@ -11,139 +11,111 @@
|
|||
#include "LaserPointerManager.h"
|
||||
|
||||
QUuid LaserPointerManager::createLaserPointer(const QVariant& rayProps, const LaserPointer::RenderStateMap& renderStates, const LaserPointer::DefaultRenderStateMap& defaultRenderStates,
|
||||
const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) {
|
||||
std::shared_ptr<LaserPointer> laserPointer = std::make_shared<LaserPointer>(rayProps, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, enabled);
|
||||
const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool distanceScaleEnd, const bool enabled) {
|
||||
QUuid result;
|
||||
std::shared_ptr<LaserPointer> laserPointer = std::make_shared<LaserPointer>(rayProps, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, distanceScaleEnd, enabled);
|
||||
if (!laserPointer->getRayUID().isNull()) {
|
||||
QWriteLocker containsLock(&_containsLock);
|
||||
QUuid id = QUuid::createUuid();
|
||||
_laserPointers[id] = laserPointer;
|
||||
return id;
|
||||
result = QUuid::createUuid();
|
||||
withWriteLock([&] { _laserPointers[result] = laserPointer; });
|
||||
}
|
||||
return QUuid();
|
||||
return result;
|
||||
}
|
||||
|
||||
void LaserPointerManager::removeLaserPointer(const QUuid uid) {
|
||||
QWriteLocker lock(&_containsLock);
|
||||
_laserPointers.remove(uid);
|
||||
|
||||
LaserPointer::Pointer LaserPointerManager::find(const QUuid& uid) const {
|
||||
return resultWithReadLock<LaserPointer::Pointer>([&] {
|
||||
auto itr = _laserPointers.find(uid);
|
||||
if (itr != _laserPointers.end()) {
|
||||
return *itr;
|
||||
}
|
||||
return LaserPointer::Pointer();
|
||||
});
|
||||
}
|
||||
|
||||
void LaserPointerManager::enableLaserPointer(const QUuid uid) {
|
||||
QReadLocker lock(&_containsLock);
|
||||
auto laserPointer = _laserPointers.find(uid);
|
||||
if (laserPointer != _laserPointers.end()) {
|
||||
laserPointer.value()->enable();
|
||||
|
||||
void LaserPointerManager::removeLaserPointer(const QUuid& uid) {
|
||||
withWriteLock([&] {
|
||||
_laserPointers.remove(uid);
|
||||
});
|
||||
}
|
||||
|
||||
void LaserPointerManager::enableLaserPointer(const QUuid& uid) const {
|
||||
auto laserPointer = find(uid);
|
||||
if (laserPointer) {
|
||||
laserPointer->enable();
|
||||
}
|
||||
}
|
||||
|
||||
void LaserPointerManager::disableLaserPointer(const QUuid uid) {
|
||||
QReadLocker lock(&_containsLock);
|
||||
auto laserPointer = _laserPointers.find(uid);
|
||||
if (laserPointer != _laserPointers.end()) {
|
||||
laserPointer.value()->disable();
|
||||
void LaserPointerManager::disableLaserPointer(const QUuid& uid) const {
|
||||
auto laserPointer = find(uid);
|
||||
if (laserPointer) {
|
||||
laserPointer->disable();
|
||||
}
|
||||
}
|
||||
|
||||
void LaserPointerManager::setRenderState(QUuid uid, const std::string& renderState) {
|
||||
QReadLocker lock(&_containsLock);
|
||||
auto laserPointer = _laserPointers.find(uid);
|
||||
if (laserPointer != _laserPointers.end()) {
|
||||
laserPointer.value()->setRenderState(renderState);
|
||||
void LaserPointerManager::setRenderState(const QUuid& uid, const std::string& renderState) const {
|
||||
auto laserPointer = find(uid);
|
||||
if (laserPointer) {
|
||||
laserPointer->setRenderState(renderState);
|
||||
}
|
||||
}
|
||||
|
||||
void LaserPointerManager::editRenderState(QUuid uid, const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) {
|
||||
QReadLocker lock(&_containsLock);
|
||||
auto laserPointer = _laserPointers.find(uid);
|
||||
if (laserPointer != _laserPointers.end()) {
|
||||
laserPointer.value()->editRenderState(state, startProps, pathProps, endProps);
|
||||
void LaserPointerManager::editRenderState(const QUuid& uid, const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) const {
|
||||
auto laserPointer = find(uid);
|
||||
if (laserPointer) {
|
||||
laserPointer->editRenderState(state, startProps, pathProps, endProps);
|
||||
}
|
||||
}
|
||||
|
||||
const RayPickResult LaserPointerManager::getPrevRayPickResult(const QUuid uid) {
|
||||
QReadLocker lock(&_containsLock);
|
||||
auto laserPointer = _laserPointers.find(uid);
|
||||
if (laserPointer != _laserPointers.end()) {
|
||||
return laserPointer.value()->getPrevRayPickResult();
|
||||
const RayPickResult LaserPointerManager::getPrevRayPickResult(const QUuid& uid) const {
|
||||
auto laserPointer = find(uid);
|
||||
if (laserPointer) {
|
||||
return laserPointer->getPrevRayPickResult();
|
||||
}
|
||||
return RayPickResult();
|
||||
}
|
||||
|
||||
void LaserPointerManager::update() {
|
||||
QReadLocker lock(&_containsLock);
|
||||
for (QUuid& uid : _laserPointers.keys()) {
|
||||
auto laserPointer = _laserPointers.find(uid);
|
||||
laserPointer.value()->update();
|
||||
auto cachedLaserPointers = resultWithReadLock<QList<std::shared_ptr<LaserPointer>>>([&] {
|
||||
return _laserPointers.values();
|
||||
});
|
||||
|
||||
for (const auto& laserPointer : cachedLaserPointers) {
|
||||
laserPointer->update();
|
||||
}
|
||||
}
|
||||
|
||||
void LaserPointerManager::setPrecisionPicking(QUuid uid, const bool precisionPicking) {
|
||||
QReadLocker lock(&_containsLock);
|
||||
auto laserPointer = _laserPointers.find(uid);
|
||||
if (laserPointer != _laserPointers.end()) {
|
||||
laserPointer.value()->setPrecisionPicking(precisionPicking);
|
||||
void LaserPointerManager::setPrecisionPicking(const QUuid& uid, const bool precisionPicking) const {
|
||||
auto laserPointer = find(uid);
|
||||
if (laserPointer) {
|
||||
laserPointer->setPrecisionPicking(precisionPicking);
|
||||
}
|
||||
}
|
||||
|
||||
void LaserPointerManager::setLaserLength(QUuid uid, const float laserLength) {
|
||||
QReadLocker lock(&_containsLock);
|
||||
auto laserPointer = _laserPointers.find(uid);
|
||||
if (laserPointer != _laserPointers.end()) {
|
||||
laserPointer.value()->setLaserLength(laserLength);
|
||||
void LaserPointerManager::setLaserLength(const QUuid& uid, const float laserLength) const {
|
||||
auto laserPointer = find(uid);
|
||||
if (laserPointer) {
|
||||
laserPointer->setLaserLength(laserLength);
|
||||
}
|
||||
}
|
||||
|
||||
void LaserPointerManager::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) {
|
||||
QReadLocker lock(&_containsLock);
|
||||
auto laserPointer = _laserPointers.find(uid);
|
||||
if (laserPointer != _laserPointers.end()) {
|
||||
laserPointer.value()->setIgnoreEntities(ignoreEntities);
|
||||
void LaserPointerManager::setIgnoreItems(const QUuid& uid, const QVector<QUuid>& ignoreEntities) const {
|
||||
auto laserPointer = find(uid);
|
||||
if (laserPointer) {
|
||||
laserPointer->setIgnoreItems(ignoreEntities);
|
||||
}
|
||||
}
|
||||
|
||||
void LaserPointerManager::setIncludeEntities(QUuid uid, const QScriptValue& includeEntities) {
|
||||
QReadLocker lock(&_containsLock);
|
||||
auto laserPointer = _laserPointers.find(uid);
|
||||
if (laserPointer != _laserPointers.end()) {
|
||||
laserPointer.value()->setIncludeEntities(includeEntities);
|
||||
void LaserPointerManager::setIncludeItems(const QUuid& uid, const QVector<QUuid>& includeEntities) const {
|
||||
auto laserPointer = find(uid);
|
||||
if (laserPointer) {
|
||||
laserPointer->setIncludeItems(includeEntities);
|
||||
}
|
||||
}
|
||||
|
||||
void LaserPointerManager::setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays) {
|
||||
QReadLocker lock(&_containsLock);
|
||||
auto laserPointer = _laserPointers.find(uid);
|
||||
if (laserPointer != _laserPointers.end()) {
|
||||
laserPointer.value()->setIgnoreOverlays(ignoreOverlays);
|
||||
}
|
||||
}
|
||||
|
||||
void LaserPointerManager::setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays) {
|
||||
QReadLocker lock(&_containsLock);
|
||||
auto laserPointer = _laserPointers.find(uid);
|
||||
if (laserPointer != _laserPointers.end()) {
|
||||
laserPointer.value()->setIncludeOverlays(includeOverlays);
|
||||
}
|
||||
}
|
||||
|
||||
void LaserPointerManager::setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars) {
|
||||
QReadLocker lock(&_containsLock);
|
||||
auto laserPointer = _laserPointers.find(uid);
|
||||
if (laserPointer != _laserPointers.end()) {
|
||||
laserPointer.value()->setIgnoreAvatars(ignoreAvatars);
|
||||
}
|
||||
}
|
||||
|
||||
void LaserPointerManager::setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars) {
|
||||
QReadLocker lock(&_containsLock);
|
||||
auto laserPointer = _laserPointers.find(uid);
|
||||
if (laserPointer != _laserPointers.end()) {
|
||||
laserPointer.value()->setIncludeAvatars(includeAvatars);
|
||||
}
|
||||
}
|
||||
|
||||
void LaserPointerManager::setLockEndUUID(QUuid uid, QUuid objectID, const bool isOverlay) {
|
||||
QReadLocker lock(&_containsLock);
|
||||
auto laserPointer = _laserPointers.find(uid);
|
||||
if (laserPointer != _laserPointers.end()) {
|
||||
laserPointer.value()->setLockEndUUID(objectID, isOverlay);
|
||||
void LaserPointerManager::setLockEndUUID(const QUuid& uid, const QUuid& objectID, const bool isOverlay) const {
|
||||
auto laserPointer = find(uid);
|
||||
if (laserPointer) {
|
||||
laserPointer->setLockEndUUID(objectID, isOverlay);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,39 +14,38 @@
|
|||
#include <memory>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <shared/ReadWriteLockable.h>
|
||||
|
||||
#include "LaserPointer.h"
|
||||
|
||||
class RayPickResult;
|
||||
|
||||
class LaserPointerManager {
|
||||
|
||||
class LaserPointerManager : protected ReadWriteLockable {
|
||||
|
||||
public:
|
||||
QUuid createLaserPointer(const QVariant& rayProps, const LaserPointer::RenderStateMap& renderStates, const LaserPointer::DefaultRenderStateMap& defaultRenderStates,
|
||||
const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled);
|
||||
void removeLaserPointer(const QUuid uid);
|
||||
void enableLaserPointer(const QUuid uid);
|
||||
void disableLaserPointer(const QUuid uid);
|
||||
void setRenderState(QUuid uid, const std::string& renderState);
|
||||
void editRenderState(QUuid uid, const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps);
|
||||
const RayPickResult getPrevRayPickResult(const QUuid uid);
|
||||
const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool distanceScaleEnd, const bool enabled);
|
||||
|
||||
void setPrecisionPicking(QUuid uid, const bool precisionPicking);
|
||||
void setLaserLength(QUuid uid, const float laserLength);
|
||||
void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities);
|
||||
void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities);
|
||||
void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays);
|
||||
void setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays);
|
||||
void setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars);
|
||||
void setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars);
|
||||
void removeLaserPointer(const QUuid& uid);
|
||||
void enableLaserPointer(const QUuid& uid) const;
|
||||
void disableLaserPointer(const QUuid& uid) const;
|
||||
void setRenderState(const QUuid& uid, const std::string& renderState) const;
|
||||
void editRenderState(const QUuid& uid, const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) const;
|
||||
const RayPickResult getPrevRayPickResult(const QUuid& uid) const;
|
||||
|
||||
void setLockEndUUID(QUuid uid, QUuid objectID, const bool isOverlay);
|
||||
void setPrecisionPicking(const QUuid& uid, const bool precisionPicking) const;
|
||||
void setLaserLength(const QUuid& uid, const float laserLength) const;
|
||||
void setIgnoreItems(const QUuid& uid, const QVector<QUuid>& ignoreEntities) const;
|
||||
void setIncludeItems(const QUuid& uid, const QVector<QUuid>& includeEntities) const;
|
||||
|
||||
void setLockEndUUID(const QUuid& uid, const QUuid& objectID, const bool isOverlay) const;
|
||||
|
||||
void update();
|
||||
|
||||
private:
|
||||
LaserPointer::Pointer find(const QUuid& uid) const;
|
||||
QHash<QUuid, std::shared_ptr<LaserPointer>> _laserPointers;
|
||||
QReadWriteLock _containsLock;
|
||||
|
||||
};
|
||||
|
||||
#endif // hifi_LaserPointerManager_h
|
||||
|
|
|
@ -11,10 +11,19 @@
|
|||
|
||||
#include "LaserPointerScriptingInterface.h"
|
||||
|
||||
#include <QVariant>
|
||||
#include "GLMHelpers.h"
|
||||
#include <QtCore/QVariant>
|
||||
|
||||
QUuid LaserPointerScriptingInterface::createLaserPointer(const QVariant& properties) {
|
||||
#include <GLMHelpers.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
||||
void LaserPointerScriptingInterface::setIgnoreItems(const QUuid& uid, const QScriptValue& ignoreItems) const {
|
||||
qApp->getLaserPointerManager().setIgnoreItems(uid, qVectorQUuidFromScriptValue(ignoreItems));
|
||||
}
|
||||
void LaserPointerScriptingInterface::setIncludeItems(const QUuid& uid, const QScriptValue& includeItems) const {
|
||||
qApp->getLaserPointerManager().setIncludeItems(uid, qVectorQUuidFromScriptValue(includeItems));
|
||||
}
|
||||
|
||||
QUuid LaserPointerScriptingInterface::createLaserPointer(const QVariant& properties) const {
|
||||
QVariantMap propertyMap = properties.toMap();
|
||||
|
||||
bool faceAvatar = false;
|
||||
|
@ -32,6 +41,11 @@ QUuid LaserPointerScriptingInterface::createLaserPointer(const QVariant& propert
|
|||
lockEnd = propertyMap["lockEnd"].toBool();
|
||||
}
|
||||
|
||||
bool distanceScaleEnd = false;
|
||||
if (propertyMap["distanceScaleEnd"].isValid()) {
|
||||
distanceScaleEnd = propertyMap["distanceScaleEnd"].toBool();
|
||||
}
|
||||
|
||||
bool enabled = false;
|
||||
if (propertyMap["enabled"].isValid()) {
|
||||
enabled = propertyMap["enabled"].toBool();
|
||||
|
@ -66,10 +80,10 @@ QUuid LaserPointerScriptingInterface::createLaserPointer(const QVariant& propert
|
|||
}
|
||||
}
|
||||
|
||||
return qApp->getLaserPointerManager().createLaserPointer(properties, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, enabled);
|
||||
return qApp->getLaserPointerManager().createLaserPointer(properties, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, distanceScaleEnd, enabled);
|
||||
}
|
||||
|
||||
void LaserPointerScriptingInterface::editRenderState(QUuid uid, const QString& renderState, const QVariant& properties) {
|
||||
void LaserPointerScriptingInterface::editRenderState(const QUuid& uid, const QString& renderState, const QVariant& properties) const {
|
||||
QVariantMap propMap = properties.toMap();
|
||||
|
||||
QVariant startProps;
|
||||
|
@ -90,7 +104,7 @@ void LaserPointerScriptingInterface::editRenderState(QUuid uid, const QString& r
|
|||
qApp->getLaserPointerManager().editRenderState(uid, renderState.toStdString(), startProps, pathProps, endProps);
|
||||
}
|
||||
|
||||
const RenderState LaserPointerScriptingInterface::buildRenderState(const QVariantMap& propMap) {
|
||||
RenderState LaserPointerScriptingInterface::buildRenderState(const QVariantMap& propMap) {
|
||||
QUuid startID;
|
||||
if (propMap["start"].isValid()) {
|
||||
QVariantMap startMap = propMap["start"].toMap();
|
||||
|
|
|
@ -22,27 +22,23 @@ class LaserPointerScriptingInterface : public QObject, public Dependency {
|
|||
SINGLETON_DEPENDENCY
|
||||
|
||||
public slots:
|
||||
Q_INVOKABLE QUuid createLaserPointer(const QVariant& properties);
|
||||
Q_INVOKABLE void enableLaserPointer(QUuid uid) { qApp->getLaserPointerManager().enableLaserPointer(uid); }
|
||||
Q_INVOKABLE void disableLaserPointer(QUuid uid) { qApp->getLaserPointerManager().disableLaserPointer(uid); }
|
||||
Q_INVOKABLE void removeLaserPointer(QUuid uid) { qApp->getLaserPointerManager().removeLaserPointer(uid); }
|
||||
Q_INVOKABLE void editRenderState(QUuid uid, const QString& renderState, const QVariant& properties);
|
||||
Q_INVOKABLE void setRenderState(QUuid uid, const QString& renderState) { qApp->getLaserPointerManager().setRenderState(uid, renderState.toStdString()); }
|
||||
Q_INVOKABLE RayPickResult getPrevRayPickResult(QUuid uid) { return qApp->getLaserPointerManager().getPrevRayPickResult(uid); }
|
||||
Q_INVOKABLE QUuid createLaserPointer(const QVariant& properties) const;
|
||||
Q_INVOKABLE void enableLaserPointer(const QUuid& uid) const { qApp->getLaserPointerManager().enableLaserPointer(uid); }
|
||||
Q_INVOKABLE void disableLaserPointer(const QUuid& uid) const { qApp->getLaserPointerManager().disableLaserPointer(uid); }
|
||||
Q_INVOKABLE void removeLaserPointer(const QUuid& uid) const { qApp->getLaserPointerManager().removeLaserPointer(uid); }
|
||||
Q_INVOKABLE void editRenderState(const QUuid& uid, const QString& renderState, const QVariant& properties) const;
|
||||
Q_INVOKABLE void setRenderState(const QUuid& uid, const QString& renderState) const { qApp->getLaserPointerManager().setRenderState(uid, renderState.toStdString()); }
|
||||
Q_INVOKABLE RayPickResult getPrevRayPickResult(QUuid uid) const { return qApp->getLaserPointerManager().getPrevRayPickResult(uid); }
|
||||
|
||||
Q_INVOKABLE void setPrecisionPicking(QUuid uid, const bool precisionPicking) { qApp->getLaserPointerManager().setPrecisionPicking(uid, precisionPicking); }
|
||||
Q_INVOKABLE void setLaserLength(QUuid uid, const float laserLength) { qApp->getLaserPointerManager().setLaserLength(uid, laserLength); }
|
||||
Q_INVOKABLE void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) { qApp->getLaserPointerManager().setIgnoreEntities(uid, ignoreEntities); }
|
||||
Q_INVOKABLE void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities) { qApp->getLaserPointerManager().setIncludeEntities(uid, includeEntities); }
|
||||
Q_INVOKABLE void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays) { qApp->getLaserPointerManager().setIgnoreOverlays(uid, ignoreOverlays); }
|
||||
Q_INVOKABLE void setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays) { qApp->getLaserPointerManager().setIncludeOverlays(uid, includeOverlays); }
|
||||
Q_INVOKABLE void setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars) { qApp->getLaserPointerManager().setIgnoreAvatars(uid, ignoreAvatars); }
|
||||
Q_INVOKABLE void setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars) { qApp->getLaserPointerManager().setIncludeAvatars(uid, includeAvatars); }
|
||||
Q_INVOKABLE void setPrecisionPicking(const QUuid& uid, bool precisionPicking) const { qApp->getLaserPointerManager().setPrecisionPicking(uid, precisionPicking); }
|
||||
Q_INVOKABLE void setLaserLength(const QUuid& uid, float laserLength) const { qApp->getLaserPointerManager().setLaserLength(uid, laserLength); }
|
||||
Q_INVOKABLE void setIgnoreItems(const QUuid& uid, const QScriptValue& ignoreEntities) const;
|
||||
Q_INVOKABLE void setIncludeItems(const QUuid& uid, const QScriptValue& includeEntities) const;
|
||||
|
||||
Q_INVOKABLE void setLockEndUUID(QUuid uid, QUuid objectID, const bool isOverlay) { qApp->getLaserPointerManager().setLockEndUUID(uid, objectID, isOverlay); }
|
||||
Q_INVOKABLE void setLockEndUUID(const QUuid& uid, const QUuid& objectID, bool isOverlay) const { qApp->getLaserPointerManager().setLockEndUUID(uid, objectID, isOverlay); }
|
||||
|
||||
private:
|
||||
const RenderState buildRenderState(const QVariantMap& propMap);
|
||||
static RenderState buildRenderState(const QVariantMap& propMap);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#ifndef hifi_MouseRayPick_h
|
||||
#define hifi_MouseRayPick_h
|
||||
|
||||
#include "RayPick.h"
|
||||
#include <pointers/rays/RayPick.h>
|
||||
|
||||
class MouseRayPick : public RayPick {
|
||||
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
//
|
||||
// RayPick.cpp
|
||||
// interface/src/raypick
|
||||
//
|
||||
// Created by Sam Gondelman 7/11/2017
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#include "RayPick.h"
|
||||
|
||||
RayPick::RayPick(const RayPickFilter& filter, const float maxDistance, const bool enabled) :
|
||||
_filter(filter),
|
||||
_maxDistance(maxDistance),
|
||||
_enabled(enabled)
|
||||
{
|
||||
}
|
||||
void RayPick::enable() {
|
||||
QWriteLocker lock(getLock());
|
||||
_enabled = true;
|
||||
}
|
||||
|
||||
void RayPick::disable() {
|
||||
QWriteLocker lock(getLock());
|
||||
_enabled = false;
|
||||
}
|
||||
|
||||
const RayPickResult& RayPick::getPrevRayPickResult() {
|
||||
QReadLocker lock(getLock());
|
||||
return _prevResult;
|
||||
}
|
||||
|
||||
void RayPick::setIgnoreEntities(const QScriptValue& ignoreEntities) {
|
||||
QWriteLocker lock(getLock());
|
||||
_ignoreEntities = qVectorEntityItemIDFromScriptValue(ignoreEntities);
|
||||
}
|
||||
|
||||
void RayPick::setIncludeEntities(const QScriptValue& includeEntities) {
|
||||
QWriteLocker lock(getLock());
|
||||
_includeEntities = qVectorEntityItemIDFromScriptValue(includeEntities);
|
||||
}
|
||||
|
||||
void RayPick::setIgnoreOverlays(const QScriptValue& ignoreOverlays) {
|
||||
QWriteLocker lock(getLock());
|
||||
_ignoreOverlays = qVectorOverlayIDFromScriptValue(ignoreOverlays);
|
||||
}
|
||||
|
||||
void RayPick::setIncludeOverlays(const QScriptValue& includeOverlays) {
|
||||
QWriteLocker lock(getLock());
|
||||
_includeOverlays = qVectorOverlayIDFromScriptValue(includeOverlays);
|
||||
}
|
||||
|
||||
void RayPick::setIgnoreAvatars(const QScriptValue& ignoreAvatars) {
|
||||
QWriteLocker lock(getLock());
|
||||
_ignoreAvatars = qVectorEntityItemIDFromScriptValue(ignoreAvatars);
|
||||
}
|
||||
|
||||
void RayPick::setIncludeAvatars(const QScriptValue& includeAvatars) {
|
||||
QWriteLocker lock(getLock());
|
||||
_includeAvatars = qVectorEntityItemIDFromScriptValue(includeAvatars);
|
||||
}
|
|
@ -10,6 +10,8 @@
|
|||
//
|
||||
#include "RayPickManager.h"
|
||||
|
||||
#include <pointers/rays/StaticRayPick.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "EntityScriptingInterface.h"
|
||||
#include "ui/overlays/Overlays.h"
|
||||
|
@ -18,45 +20,50 @@
|
|||
#include "DependencyManager.h"
|
||||
|
||||
#include "JointRayPick.h"
|
||||
#include "StaticRayPick.h"
|
||||
#include "MouseRayPick.h"
|
||||
|
||||
bool RayPickManager::checkAndCompareCachedResults(QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache, RayPickResult& res, const RayPickFilter::Flags& mask) {
|
||||
if (cache.contains(ray) && cache[ray].find(mask) != cache[ray].end()) {
|
||||
if (cache[ray][mask].distance < res.distance) {
|
||||
res = cache[ray][mask];
|
||||
bool RayPickManager::checkAndCompareCachedResults(QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache, RayPickResult& res, const RayCacheKey& key) {
|
||||
if (cache.contains(ray) && cache[ray].find(key) != cache[ray].end()) {
|
||||
if (cache[ray][key].distance < res.distance) {
|
||||
res = cache[ray][key];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void RayPickManager::cacheResult(const bool intersects, const RayPickResult& resTemp, const RayPickFilter::Flags& mask, RayPickResult& res, QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache) {
|
||||
void RayPickManager::cacheResult(const bool intersects, const RayPickResult& resTemp, const RayCacheKey& key, RayPickResult& res, QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache) {
|
||||
if (intersects) {
|
||||
cache[ray][mask] = resTemp;
|
||||
cache[ray][key] = resTemp;
|
||||
if (resTemp.distance < res.distance) {
|
||||
res = resTemp;
|
||||
}
|
||||
} else {
|
||||
cache[ray][mask] = RayPickResult(res.searchRay);
|
||||
cache[ray][key] = RayPickResult(res.searchRay);
|
||||
}
|
||||
}
|
||||
|
||||
void RayPickManager::update() {
|
||||
QReadLocker lock(&_containsLock);
|
||||
RayPickCache results;
|
||||
for (auto& uid : _rayPicks.keys()) {
|
||||
std::shared_ptr<RayPick> rayPick = _rayPicks[uid];
|
||||
QWriteLocker lock(rayPick->getLock());
|
||||
QHash<QUuid, RayPick::Pointer> cachedRayPicks;
|
||||
withReadLock([&] {
|
||||
cachedRayPicks = _rayPicks;
|
||||
});
|
||||
|
||||
for (const auto& uid : cachedRayPicks.keys()) {
|
||||
std::shared_ptr<RayPick> rayPick = cachedRayPicks[uid];
|
||||
if (!rayPick->isEnabled() || rayPick->getFilter().doesPickNothing() || rayPick->getMaxDistance() < 0.0f) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool valid;
|
||||
PickRay ray = rayPick->getPickRay(valid);
|
||||
PickRay ray;
|
||||
|
||||
if (!valid) {
|
||||
continue;
|
||||
{
|
||||
bool valid;
|
||||
ray = rayPick->getPickRay(valid);
|
||||
if (!valid) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
QPair<glm::vec3, glm::vec3> rayKey = QPair<glm::vec3, glm::vec3>(ray.origin, ray.direction);
|
||||
|
@ -67,16 +74,16 @@ void RayPickManager::update() {
|
|||
bool fromCache = true;
|
||||
bool invisible = rayPick->getFilter().doesPickInvisible();
|
||||
bool nonCollidable = rayPick->getFilter().doesPickNonCollidable();
|
||||
RayPickFilter::Flags entityMask = rayPick->getFilter().getEntityFlags();
|
||||
if (!checkAndCompareCachedResults(rayKey, results, res, entityMask)) {
|
||||
entityRes = DependencyManager::get<EntityScriptingInterface>()->findRayIntersectionVector(ray, !rayPick->getFilter().doesPickCourse(),
|
||||
rayPick->getIncludeEntites(), rayPick->getIgnoreEntites(), !invisible, !nonCollidable);
|
||||
RayCacheKey entityKey = { rayPick->getFilter().getEntityFlags(), rayPick->getIncludeItems(), rayPick->getIgnoreItems() };
|
||||
if (!checkAndCompareCachedResults(rayKey, results, res, entityKey)) {
|
||||
entityRes = DependencyManager::get<EntityScriptingInterface>()->findRayIntersectionVector(ray, !rayPick->getFilter().doesPickCoarse(),
|
||||
rayPick->getIncludeItemsAs<EntityItemID>(), rayPick->getIgnoreItemsAs<EntityItemID>(), !invisible, !nonCollidable);
|
||||
fromCache = false;
|
||||
}
|
||||
|
||||
if (!fromCache) {
|
||||
cacheResult(entityRes.intersects, RayPickResult(IntersectionType::ENTITY, entityRes.entityID, entityRes.distance, entityRes.intersection, ray, entityRes.surfaceNormal),
|
||||
entityMask, res, rayKey, results);
|
||||
entityKey, res, rayKey, results);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,33 +92,34 @@ void RayPickManager::update() {
|
|||
bool fromCache = true;
|
||||
bool invisible = rayPick->getFilter().doesPickInvisible();
|
||||
bool nonCollidable = rayPick->getFilter().doesPickNonCollidable();
|
||||
RayPickFilter::Flags overlayMask = rayPick->getFilter().getOverlayFlags();
|
||||
if (!checkAndCompareCachedResults(rayKey, results, res, overlayMask)) {
|
||||
overlayRes = qApp->getOverlays().findRayIntersectionVector(ray, !rayPick->getFilter().doesPickCourse(),
|
||||
rayPick->getIncludeOverlays(), rayPick->getIgnoreOverlays(), !invisible, !nonCollidable);
|
||||
RayCacheKey overlayKey = { rayPick->getFilter().getOverlayFlags(), rayPick->getIncludeItems(), rayPick->getIgnoreItems() };
|
||||
if (!checkAndCompareCachedResults(rayKey, results, res, overlayKey)) {
|
||||
overlayRes = qApp->getOverlays().findRayIntersectionVector(ray, !rayPick->getFilter().doesPickCoarse(),
|
||||
rayPick->getIncludeItemsAs<OverlayID>(), rayPick->getIgnoreItemsAs<OverlayID>(), !invisible, !nonCollidable);
|
||||
fromCache = false;
|
||||
}
|
||||
|
||||
if (!fromCache) {
|
||||
cacheResult(overlayRes.intersects, RayPickResult(IntersectionType::OVERLAY, overlayRes.overlayID, overlayRes.distance, overlayRes.intersection, ray, overlayRes.surfaceNormal),
|
||||
overlayMask, res, rayKey, results);
|
||||
overlayKey, res, rayKey, results);
|
||||
}
|
||||
}
|
||||
|
||||
if (rayPick->getFilter().doesPickAvatars()) {
|
||||
RayPickFilter::Flags avatarMask = rayPick->getFilter().getAvatarFlags();
|
||||
if (!checkAndCompareCachedResults(rayKey, results, res, avatarMask)) {
|
||||
RayToAvatarIntersectionResult avatarRes = DependencyManager::get<AvatarManager>()->findRayIntersectionVector(ray, rayPick->getIncludeAvatars(), rayPick->getIgnoreAvatars());
|
||||
cacheResult(avatarRes.intersects, RayPickResult(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.intersection, ray), avatarMask, res, rayKey, results);
|
||||
RayCacheKey avatarKey = { rayPick->getFilter().getAvatarFlags(), rayPick->getIncludeItems(), rayPick->getIgnoreItems() };
|
||||
if (!checkAndCompareCachedResults(rayKey, results, res, avatarKey)) {
|
||||
RayToAvatarIntersectionResult avatarRes = DependencyManager::get<AvatarManager>()->findRayIntersectionVector(ray,
|
||||
rayPick->getIncludeItemsAs<EntityItemID>(), rayPick->getIgnoreItemsAs<EntityItemID>());
|
||||
cacheResult(avatarRes.intersects, RayPickResult(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.intersection, ray), avatarKey, res, rayKey, results);
|
||||
}
|
||||
}
|
||||
|
||||
// Can't intersect with HUD in desktop mode
|
||||
if (rayPick->getFilter().doesPickHUD() && DependencyManager::get<HMDScriptingInterface>()->isHMDMode()) {
|
||||
RayPickFilter::Flags hudMask = rayPick->getFilter().getHUDFlags();
|
||||
if (!checkAndCompareCachedResults(rayKey, results, res, hudMask)) {
|
||||
RayCacheKey hudKey = { rayPick->getFilter().getHUDFlags(), QVector<QUuid>(), QVector<QUuid>() };
|
||||
if (!checkAndCompareCachedResults(rayKey, results, res, hudKey)) {
|
||||
glm::vec3 hudRes = DependencyManager::get<HMDScriptingInterface>()->calculateRayUICollisionPoint(ray.origin, ray.direction);
|
||||
cacheResult(true, RayPickResult(IntersectionType::HUD, 0, glm::distance(ray.origin, hudRes), hudRes, ray), hudMask, res, rayKey, results);
|
||||
cacheResult(true, RayPickResult(IntersectionType::HUD, 0, glm::distance(ray.origin, hudRes), hudRes, ray), hudKey, res, rayKey, results);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -123,109 +131,87 @@ void RayPickManager::update() {
|
|||
}
|
||||
}
|
||||
|
||||
QUuid RayPickManager::createRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const RayPickFilter& filter, const float maxDistance, const bool enabled) {
|
||||
QWriteLocker lock(&_containsLock);
|
||||
QUuid RayPickManager::createRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const RayPickFilter& filter, float maxDistance, bool enabled) {
|
||||
auto newRayPick = std::make_shared<JointRayPick>(jointName, posOffset, dirOffset, filter, maxDistance, enabled);
|
||||
QUuid id = QUuid::createUuid();
|
||||
_rayPicks[id] = std::make_shared<JointRayPick>(jointName, posOffset, dirOffset, filter, maxDistance, enabled);
|
||||
withWriteLock([&] {
|
||||
_rayPicks[id] = newRayPick;
|
||||
});
|
||||
return id;
|
||||
}
|
||||
|
||||
QUuid RayPickManager::createRayPick(const RayPickFilter& filter, const float maxDistance, const bool enabled) {
|
||||
QWriteLocker lock(&_containsLock);
|
||||
QUuid RayPickManager::createRayPick(const RayPickFilter& filter, float maxDistance, bool enabled) {
|
||||
QUuid id = QUuid::createUuid();
|
||||
_rayPicks[id] = std::make_shared<MouseRayPick>(filter, maxDistance, enabled);
|
||||
auto newRayPick = std::make_shared<MouseRayPick>(filter, maxDistance, enabled);
|
||||
withWriteLock([&] {
|
||||
_rayPicks[id] = newRayPick;
|
||||
});
|
||||
return id;
|
||||
}
|
||||
|
||||
QUuid RayPickManager::createRayPick(const glm::vec3& position, const glm::vec3& direction, const RayPickFilter& filter, const float maxDistance, const bool enabled) {
|
||||
QWriteLocker lock(&_containsLock);
|
||||
QUuid RayPickManager::createRayPick(const glm::vec3& position, const glm::vec3& direction, const RayPickFilter& filter, float maxDistance, bool enabled) {
|
||||
QUuid id = QUuid::createUuid();
|
||||
_rayPicks[id] = std::make_shared<StaticRayPick>(position, direction, filter, maxDistance, enabled);
|
||||
auto newRayPick = std::make_shared<StaticRayPick>(position, direction, filter, maxDistance, enabled);
|
||||
withWriteLock([&] {
|
||||
_rayPicks[id] = newRayPick;
|
||||
});
|
||||
return id;
|
||||
}
|
||||
|
||||
void RayPickManager::removeRayPick(const QUuid uid) {
|
||||
QWriteLocker lock(&_containsLock);
|
||||
_rayPicks.remove(uid);
|
||||
void RayPickManager::removeRayPick(const QUuid& uid) {
|
||||
withWriteLock([&] {
|
||||
_rayPicks.remove(uid);
|
||||
});
|
||||
}
|
||||
|
||||
void RayPickManager::enableRayPick(const QUuid uid) {
|
||||
QReadLocker containsLock(&_containsLock);
|
||||
auto rayPick = _rayPicks.find(uid);
|
||||
if (rayPick != _rayPicks.end()) {
|
||||
rayPick.value()->enable();
|
||||
RayPick::Pointer RayPickManager::findRayPick(const QUuid& uid) const {
|
||||
return resultWithReadLock<RayPick::Pointer>([&] {
|
||||
if (_rayPicks.contains(uid)) {
|
||||
return _rayPicks[uid];
|
||||
}
|
||||
return RayPick::Pointer();
|
||||
});
|
||||
}
|
||||
|
||||
void RayPickManager::enableRayPick(const QUuid& uid) const {
|
||||
auto rayPick = findRayPick(uid);
|
||||
if (rayPick) {
|
||||
rayPick->enable();
|
||||
}
|
||||
}
|
||||
|
||||
void RayPickManager::disableRayPick(const QUuid uid) {
|
||||
QReadLocker containsLock(&_containsLock);
|
||||
auto rayPick = _rayPicks.find(uid);
|
||||
if (rayPick != _rayPicks.end()) {
|
||||
rayPick.value()->disable();
|
||||
void RayPickManager::disableRayPick(const QUuid& uid) const {
|
||||
auto rayPick = findRayPick(uid);
|
||||
if (rayPick) {
|
||||
rayPick->disable();
|
||||
}
|
||||
}
|
||||
|
||||
const RayPickResult RayPickManager::getPrevRayPickResult(const QUuid uid) {
|
||||
QReadLocker containsLock(&_containsLock);
|
||||
auto rayPick = _rayPicks.find(uid);
|
||||
if (rayPick != _rayPicks.end()) {
|
||||
return rayPick.value()->getPrevRayPickResult();
|
||||
RayPickResult RayPickManager::getPrevRayPickResult(const QUuid& uid) const {
|
||||
auto rayPick = findRayPick(uid);
|
||||
if (rayPick) {
|
||||
return rayPick->getPrevRayPickResult();
|
||||
}
|
||||
return RayPickResult();
|
||||
}
|
||||
|
||||
void RayPickManager::setPrecisionPicking(QUuid uid, const bool precisionPicking) {
|
||||
QReadLocker containsLock(&_containsLock);
|
||||
auto rayPick = _rayPicks.find(uid);
|
||||
if (rayPick != _rayPicks.end()) {
|
||||
rayPick.value()->setPrecisionPicking(precisionPicking);
|
||||
void RayPickManager::setPrecisionPicking(const QUuid& uid, bool precisionPicking) const {
|
||||
auto rayPick = findRayPick(uid);
|
||||
if (rayPick) {
|
||||
rayPick->setPrecisionPicking(precisionPicking);
|
||||
}
|
||||
}
|
||||
|
||||
void RayPickManager::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) {
|
||||
QReadLocker containsLock(&_containsLock);
|
||||
auto rayPick = _rayPicks.find(uid);
|
||||
if (rayPick != _rayPicks.end()) {
|
||||
rayPick.value()->setIgnoreEntities(ignoreEntities);
|
||||
void RayPickManager::setIgnoreItems(const QUuid& uid, const QVector<QUuid>& ignore) const {
|
||||
auto rayPick = findRayPick(uid);
|
||||
if (rayPick) {
|
||||
rayPick->setIgnoreItems(ignore);
|
||||
}
|
||||
}
|
||||
|
||||
void RayPickManager::setIncludeEntities(QUuid uid, const QScriptValue& includeEntities) {
|
||||
QReadLocker containsLock(&_containsLock);
|
||||
auto rayPick = _rayPicks.find(uid);
|
||||
if (rayPick != _rayPicks.end()) {
|
||||
rayPick.value()->setIncludeEntities(includeEntities);
|
||||
void RayPickManager::setIncludeItems(const QUuid& uid, const QVector<QUuid>& include) const {
|
||||
auto rayPick = findRayPick(uid);
|
||||
if (rayPick) {
|
||||
rayPick->setIncludeItems(include);
|
||||
}
|
||||
}
|
||||
|
||||
void RayPickManager::setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays) {
|
||||
QReadLocker containsLock(&_containsLock);
|
||||
auto rayPick = _rayPicks.find(uid);
|
||||
if (rayPick != _rayPicks.end()) {
|
||||
rayPick.value()->setIgnoreOverlays(ignoreOverlays);
|
||||
}
|
||||
}
|
||||
|
||||
void RayPickManager::setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays) {
|
||||
QReadLocker containsLock(&_containsLock);
|
||||
auto rayPick = _rayPicks.find(uid);
|
||||
if (rayPick != _rayPicks.end()) {
|
||||
rayPick.value()->setIncludeOverlays(includeOverlays);
|
||||
}
|
||||
}
|
||||
|
||||
void RayPickManager::setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars) {
|
||||
QReadLocker containsLock(&_containsLock);
|
||||
auto rayPick = _rayPicks.find(uid);
|
||||
if (rayPick != _rayPicks.end()) {
|
||||
rayPick.value()->setIgnoreAvatars(ignoreAvatars);
|
||||
}
|
||||
}
|
||||
|
||||
void RayPickManager::setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars) {
|
||||
QReadLocker containsLock(&_containsLock);
|
||||
auto rayPick = _rayPicks.find(uid);
|
||||
if (rayPick != _rayPicks.end()) {
|
||||
rayPick.value()->setIncludeAvatars(includeAvatars);
|
||||
}
|
||||
}
|
|
@ -11,19 +11,39 @@
|
|||
#ifndef hifi_RayPickManager_h
|
||||
#define hifi_RayPickManager_h
|
||||
|
||||
#include "RayPick.h"
|
||||
|
||||
#include <memory>
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include "RegisteredMetaTypes.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <queue>
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include <RegisteredMetaTypes.h>
|
||||
#include <pointers/rays/RayPick.h>
|
||||
|
||||
|
||||
class RayPickResult;
|
||||
|
||||
class RayPickManager {
|
||||
typedef struct RayCacheKey {
|
||||
RayPickFilter::Flags mask;
|
||||
QVector<QUuid> include;
|
||||
QVector<QUuid> ignore;
|
||||
|
||||
bool operator==(const RayCacheKey& other) const {
|
||||
return (mask == other.mask && include == other.include && ignore == other.ignore);
|
||||
}
|
||||
} RayCacheKey;
|
||||
|
||||
namespace std {
|
||||
template <>
|
||||
struct hash<RayCacheKey> {
|
||||
size_t operator()(const RayCacheKey& k) const {
|
||||
return ((hash<RayPickFilter::Flags>()(k.mask) ^ (qHash(k.include) << 1)) >> 1) ^ (qHash(k.ignore) << 1);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
class RayPickManager : protected ReadWriteLockable {
|
||||
|
||||
public:
|
||||
void update();
|
||||
|
@ -31,28 +51,24 @@ public:
|
|||
QUuid createRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const RayPickFilter& filter, const float maxDistance, const bool enabled);
|
||||
QUuid createRayPick(const RayPickFilter& filter, const float maxDistance, const bool enabled);
|
||||
QUuid createRayPick(const glm::vec3& position, const glm::vec3& direction, const RayPickFilter& filter, const float maxDistance, const bool enabled);
|
||||
void removeRayPick(const QUuid uid);
|
||||
void enableRayPick(const QUuid uid);
|
||||
void disableRayPick(const QUuid uid);
|
||||
const RayPickResult getPrevRayPickResult(const QUuid uid);
|
||||
void removeRayPick(const QUuid& uid);
|
||||
void enableRayPick(const QUuid& uid) const;
|
||||
void disableRayPick(const QUuid& uid) const;
|
||||
RayPickResult getPrevRayPickResult(const QUuid& uid) const;
|
||||
|
||||
void setPrecisionPicking(QUuid uid, const bool precisionPicking);
|
||||
void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities);
|
||||
void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities);
|
||||
void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays);
|
||||
void setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays);
|
||||
void setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars);
|
||||
void setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars);
|
||||
void setPrecisionPicking(const QUuid& uid, bool precisionPicking) const;
|
||||
void setIgnoreItems(const QUuid& uid, const QVector<QUuid>& ignore) const;
|
||||
void setIncludeItems(const QUuid& uid, const QVector<QUuid>& include) const;
|
||||
|
||||
private:
|
||||
QHash<QUuid, std::shared_ptr<RayPick>> _rayPicks;
|
||||
QReadWriteLock _containsLock;
|
||||
RayPick::Pointer findRayPick(const QUuid& uid) const;
|
||||
QHash<QUuid, RayPick::Pointer> _rayPicks;
|
||||
|
||||
typedef QHash<QPair<glm::vec3, glm::vec3>, std::unordered_map<RayPickFilter::Flags, RayPickResult>> RayPickCache;
|
||||
typedef QHash<QPair<glm::vec3, glm::vec3>, std::unordered_map<RayCacheKey, RayPickResult>> RayPickCache;
|
||||
|
||||
// Returns true if this ray exists in the cache, and if it does, update res if the cached result is closer
|
||||
bool checkAndCompareCachedResults(QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache, RayPickResult& res, const RayPickFilter::Flags& mask);
|
||||
void cacheResult(const bool intersects, const RayPickResult& resTemp, const RayPickFilter::Flags& mask, RayPickResult& res, QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache);
|
||||
bool checkAndCompareCachedResults(QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache, RayPickResult& res, const RayCacheKey& key);
|
||||
void cacheResult(const bool intersects, const RayPickResult& resTemp, const RayCacheKey& key, RayPickResult& res, QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache);
|
||||
};
|
||||
|
||||
#endif // hifi_RayPickManager_h
|
|
@ -66,46 +66,30 @@ QUuid RayPickScriptingInterface::createRayPick(const QVariant& properties) {
|
|||
return QUuid();
|
||||
}
|
||||
|
||||
void RayPickScriptingInterface::enableRayPick(QUuid uid) {
|
||||
void RayPickScriptingInterface::enableRayPick(const QUuid& uid) {
|
||||
qApp->getRayPickManager().enableRayPick(uid);
|
||||
}
|
||||
|
||||
void RayPickScriptingInterface::disableRayPick(QUuid uid) {
|
||||
void RayPickScriptingInterface::disableRayPick(const QUuid& uid) {
|
||||
qApp->getRayPickManager().disableRayPick(uid);
|
||||
}
|
||||
|
||||
void RayPickScriptingInterface::removeRayPick(QUuid uid) {
|
||||
void RayPickScriptingInterface::removeRayPick(const QUuid& uid) {
|
||||
qApp->getRayPickManager().removeRayPick(uid);
|
||||
}
|
||||
|
||||
RayPickResult RayPickScriptingInterface::getPrevRayPickResult(QUuid uid) {
|
||||
RayPickResult RayPickScriptingInterface::getPrevRayPickResult(const QUuid& uid) {
|
||||
return qApp->getRayPickManager().getPrevRayPickResult(uid);
|
||||
}
|
||||
|
||||
void RayPickScriptingInterface::setPrecisionPicking(QUuid uid, const bool precisionPicking) {
|
||||
void RayPickScriptingInterface::setPrecisionPicking(const QUuid& uid, const bool precisionPicking) {
|
||||
qApp->getRayPickManager().setPrecisionPicking(uid, precisionPicking);
|
||||
}
|
||||
|
||||
void RayPickScriptingInterface::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) {
|
||||
qApp->getRayPickManager().setIgnoreEntities(uid, ignoreEntities);
|
||||
void RayPickScriptingInterface::setIgnoreItems(const QUuid& uid, const QScriptValue& ignoreItems) {
|
||||
qApp->getRayPickManager().setIgnoreItems(uid, qVectorQUuidFromScriptValue(ignoreItems));
|
||||
}
|
||||
|
||||
void RayPickScriptingInterface::setIncludeEntities(QUuid uid, const QScriptValue& includeEntities) {
|
||||
qApp->getRayPickManager().setIncludeEntities(uid, includeEntities);
|
||||
}
|
||||
|
||||
void RayPickScriptingInterface::setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays) {
|
||||
qApp->getRayPickManager().setIgnoreOverlays(uid, ignoreOverlays);
|
||||
}
|
||||
|
||||
void RayPickScriptingInterface::setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays) {
|
||||
qApp->getRayPickManager().setIncludeOverlays(uid, includeOverlays);
|
||||
}
|
||||
|
||||
void RayPickScriptingInterface::setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars) {
|
||||
qApp->getRayPickManager().setIgnoreAvatars(uid, ignoreAvatars);
|
||||
}
|
||||
|
||||
void RayPickScriptingInterface::setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars) {
|
||||
qApp->getRayPickManager().setIncludeAvatars(uid, includeAvatars);
|
||||
void RayPickScriptingInterface::setIncludeItems(const QUuid& uid, const QScriptValue& includeItems) {
|
||||
qApp->getRayPickManager().setIncludeItems(uid, qVectorQUuidFromScriptValue(includeItems));
|
||||
}
|
||||
|
|
|
@ -13,10 +13,9 @@
|
|||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include "RegisteredMetaTypes.h"
|
||||
#include "DependencyManager.h"
|
||||
|
||||
#include "RayPick.h"
|
||||
#include <RegisteredMetaTypes.h>
|
||||
#include <DependencyManager.h>
|
||||
#include <pointers/rays/RayPick.h>
|
||||
|
||||
class RayPickScriptingInterface : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
|
@ -25,7 +24,7 @@ class RayPickScriptingInterface : public QObject, public Dependency {
|
|||
Q_PROPERTY(unsigned int PICK_OVERLAYS READ PICK_OVERLAYS CONSTANT)
|
||||
Q_PROPERTY(unsigned int PICK_AVATARS READ PICK_AVATARS CONSTANT)
|
||||
Q_PROPERTY(unsigned int PICK_HUD READ PICK_HUD CONSTANT)
|
||||
Q_PROPERTY(unsigned int PICK_COURSE READ PICK_COURSE CONSTANT)
|
||||
Q_PROPERTY(unsigned int PICK_COARSE READ PICK_COARSE CONSTANT)
|
||||
Q_PROPERTY(unsigned int PICK_INCLUDE_INVISIBLE READ PICK_INCLUDE_INVISIBLE CONSTANT)
|
||||
Q_PROPERTY(unsigned int PICK_INCLUDE_NONCOLLIDABLE READ PICK_INCLUDE_NONCOLLIDABLE CONSTANT)
|
||||
Q_PROPERTY(unsigned int PICK_ALL_INTERSECTIONS READ PICK_ALL_INTERSECTIONS CONSTANT)
|
||||
|
@ -38,25 +37,21 @@ class RayPickScriptingInterface : public QObject, public Dependency {
|
|||
|
||||
public slots:
|
||||
Q_INVOKABLE QUuid createRayPick(const QVariant& properties);
|
||||
Q_INVOKABLE void enableRayPick(QUuid uid);
|
||||
Q_INVOKABLE void disableRayPick(QUuid uid);
|
||||
Q_INVOKABLE void removeRayPick(QUuid uid);
|
||||
Q_INVOKABLE RayPickResult getPrevRayPickResult(QUuid uid);
|
||||
Q_INVOKABLE void enableRayPick(const QUuid& uid);
|
||||
Q_INVOKABLE void disableRayPick(const QUuid& uid);
|
||||
Q_INVOKABLE void removeRayPick(const QUuid& uid);
|
||||
Q_INVOKABLE RayPickResult getPrevRayPickResult(const QUuid& uid);
|
||||
|
||||
Q_INVOKABLE void setPrecisionPicking(QUuid uid, const bool precisionPicking);
|
||||
Q_INVOKABLE void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities);
|
||||
Q_INVOKABLE void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities);
|
||||
Q_INVOKABLE void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays);
|
||||
Q_INVOKABLE void setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays);
|
||||
Q_INVOKABLE void setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars);
|
||||
Q_INVOKABLE void setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars);
|
||||
Q_INVOKABLE void setPrecisionPicking(const QUuid& uid, const bool precisionPicking);
|
||||
Q_INVOKABLE void setIgnoreItems(const QUuid& uid, const QScriptValue& ignoreEntities);
|
||||
Q_INVOKABLE void setIncludeItems(const QUuid& uid, const QScriptValue& includeEntities);
|
||||
|
||||
unsigned int PICK_NOTHING() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_NOTHING); }
|
||||
unsigned int PICK_NOTHING() { return 0; }
|
||||
unsigned int PICK_ENTITIES() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_ENTITIES); }
|
||||
unsigned int PICK_OVERLAYS() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_OVERLAYS); }
|
||||
unsigned int PICK_AVATARS() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_AVATARS); }
|
||||
unsigned int PICK_HUD() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_HUD); }
|
||||
unsigned int PICK_COURSE() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_COURSE); }
|
||||
unsigned int PICK_COARSE() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_COARSE); }
|
||||
unsigned int PICK_INCLUDE_INVISIBLE() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_INCLUDE_INVISIBLE); }
|
||||
unsigned int PICK_INCLUDE_NONCOLLIDABLE() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_INCLUDE_NONCOLLIDABLE); }
|
||||
unsigned int PICK_ALL_INTERSECTIONS() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_ALL_INTERSECTIONS); }
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// interface/src/ui/overlays
|
||||
//
|
||||
// Created by Zander Otavka on 8/7/15.
|
||||
// Modified by Daniela Fontes on 24/10/17.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
|
@ -13,6 +14,7 @@
|
|||
|
||||
#include <Application.h>
|
||||
#include <Transform.h>
|
||||
#include "avatar/AvatarManager.h"
|
||||
|
||||
void Billboardable::setProperties(const QVariantMap& properties) {
|
||||
auto isFacingAvatar = properties["isFacingAvatar"];
|
||||
|
@ -32,10 +34,11 @@ bool Billboardable::pointTransformAtCamera(Transform& transform, glm::quat offse
|
|||
if (isFacingAvatar()) {
|
||||
glm::vec3 billboardPos = transform.getTranslation();
|
||||
glm::vec3 cameraPos = qApp->getCamera().getPosition();
|
||||
glm::vec3 look = cameraPos - billboardPos;
|
||||
float elevation = -asinf(look.y / glm::length(look));
|
||||
float azimuth = atan2f(look.x, look.z);
|
||||
glm::quat rotation(glm::vec3(elevation, azimuth, 0));
|
||||
// use the referencial from the avatar, y isn't always up
|
||||
glm::vec3 avatarUP = DependencyManager::get<AvatarManager>()->getMyAvatar()->getOrientation()*Vectors::UP;
|
||||
|
||||
glm::quat rotation(conjugate(toQuat(glm::lookAt(billboardPos, cameraPos, avatarUP))));
|
||||
|
||||
transform.setRotation(rotation);
|
||||
transform.postRotate(offsetRotation);
|
||||
return true;
|
||||
|
|
|
@ -143,8 +143,8 @@ bool ContextOverlayInterface::createOrDestroyContextOverlay(const EntityItemID&
|
|||
if (event.getID() == LEFT_HAND_HW_ID) {
|
||||
offsetAngle *= -1.0f;
|
||||
}
|
||||
contextOverlayPosition = (glm::quat(glm::radians(glm::vec3(0.0f, offsetAngle, 0.0f)))) *
|
||||
((cameraPosition + direction * (distance - CONTEXT_OVERLAY_OFFSET_DISTANCE)));
|
||||
contextOverlayPosition = cameraPosition +
|
||||
(glm::quat(glm::radians(glm::vec3(0.0f, offsetAngle, 0.0f)))) * (direction * (distance - CONTEXT_OVERLAY_OFFSET_DISTANCE));
|
||||
contextOverlayDimensions = glm::vec2(CONTEXT_OVERLAY_SIZE, CONTEXT_OVERLAY_SIZE) * glm::distance(contextOverlayPosition, cameraPosition);
|
||||
}
|
||||
|
||||
|
|
|
@ -51,13 +51,11 @@ void Image3DOverlay::update(float deltatime) {
|
|||
_texture = DependencyManager::get<TextureCache>()->getTexture(_url);
|
||||
_textureIsLoaded = false;
|
||||
}
|
||||
#if OVERLAY_PANELS
|
||||
if (usecTimestampNow() > _transformExpiry) {
|
||||
Transform transform = getTransform();
|
||||
applyTransformTo(transform);
|
||||
setTransform(transform);
|
||||
}
|
||||
#endif
|
||||
Parent::update(deltatime);
|
||||
}
|
||||
|
||||
|
|
|
@ -96,6 +96,7 @@ void Line3DOverlay::setEnd(const glm::vec3& end) {
|
|||
} else {
|
||||
_direction = glm::vec3(0.0f);
|
||||
}
|
||||
notifyRenderTransformChange();
|
||||
}
|
||||
|
||||
void Line3DOverlay::setLocalEnd(const glm::vec3& localEnd) {
|
||||
|
|
|
@ -257,7 +257,3 @@ bool Text3DOverlay::findRayIntersection(const glm::vec3 &origin, const glm::vec3
|
|||
return Billboard3DOverlay::findRayIntersection(origin, direction, distance, face, surfaceNormal);
|
||||
}
|
||||
|
||||
Transform Text3DOverlay::evalRenderTransform() {
|
||||
return Parent::evalRenderTransform();
|
||||
}
|
||||
|
||||
|
|
|
@ -65,9 +65,6 @@ public:
|
|||
|
||||
virtual Text3DOverlay* createClone() const override;
|
||||
|
||||
protected:
|
||||
Transform evalRenderTransform() override;
|
||||
|
||||
private:
|
||||
TextRenderer3D* _textRenderer = nullptr;
|
||||
|
||||
|
|
|
@ -63,7 +63,6 @@ static const float OPAQUE_ALPHA_THRESHOLD = 0.99f;
|
|||
|
||||
const QString Web3DOverlay::TYPE = "web3d";
|
||||
const QString Web3DOverlay::QML = "Web3DOverlay.qml";
|
||||
|
||||
Web3DOverlay::Web3DOverlay() : _dpi(DPI) {
|
||||
_touchDevice.setCapabilities(QTouchDevice::Position);
|
||||
_touchDevice.setType(QTouchDevice::TouchScreen);
|
||||
|
@ -226,6 +225,9 @@ void Web3DOverlay::setupQmlSurface() {
|
|||
|
||||
_webSurface->getSurfaceContext()->setContextProperty("pathToFonts", "../../");
|
||||
|
||||
// Tablet inteference with Tablet.qml. Need to avoid this in QML space
|
||||
_webSurface->getSurfaceContext()->setContextProperty("tabletInterface", DependencyManager::get<TabletScriptingInterface>().data());
|
||||
|
||||
tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", _webSurface.data());
|
||||
// mark the TabletProxy object as cpp ownership.
|
||||
QObject* tablet = tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system");
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "AnimUtil.h"
|
||||
#include "IKTarget.h"
|
||||
|
||||
|
||||
static int nextRigId = 1;
|
||||
static std::map<int, Rig*> rigRegistry;
|
||||
static std::mutex rigRegistryMutex;
|
||||
|
@ -999,14 +1000,13 @@ void Rig::updateAnimationStateHandlers() { // called on avatar update thread (wh
|
|||
}
|
||||
|
||||
void Rig::updateAnimations(float deltaTime, const glm::mat4& rootTransform, const glm::mat4& rigToWorldTransform) {
|
||||
|
||||
PROFILE_RANGE_EX(simulation_animation_detail, __FUNCTION__, 0xffff00ff, 0);
|
||||
PerformanceTimer perfTimer("updateAnimations");
|
||||
DETAILED_PROFILE_RANGE_EX(simulation_animation_detail, __FUNCTION__, 0xffff00ff, 0);
|
||||
DETAILED_PERFORMANCE_TIMER("updateAnimations");
|
||||
|
||||
setModelOffset(rootTransform);
|
||||
|
||||
if (_animNode && _enabledAnimations) {
|
||||
PerformanceTimer perfTimer("handleTriggers");
|
||||
DETAILED_PERFORMANCE_TIMER("handleTriggers");
|
||||
|
||||
updateAnimationStateHandlers();
|
||||
_animVars.setRigToGeometryTransform(_rigToGeometryTransform);
|
||||
|
@ -1658,7 +1658,7 @@ bool Rig::getModelRegistrationPoint(glm::vec3& modelRegistrationPointOut) const
|
|||
}
|
||||
|
||||
void Rig::applyOverridePoses() {
|
||||
PerformanceTimer perfTimer("override");
|
||||
DETAILED_PERFORMANCE_TIMER("override");
|
||||
if (_numOverrides == 0 || !_animSkeleton) {
|
||||
return;
|
||||
}
|
||||
|
@ -1675,7 +1675,7 @@ void Rig::applyOverridePoses() {
|
|||
}
|
||||
|
||||
void Rig::buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& absolutePosesOut) {
|
||||
PerformanceTimer perfTimer("buildAbsolute");
|
||||
DETAILED_PERFORMANCE_TIMER("buildAbsolute");
|
||||
if (!_animSkeleton) {
|
||||
return;
|
||||
}
|
||||
|
@ -1730,8 +1730,9 @@ void Rig::copyJointsIntoJointData(QVector<JointData>& jointDataVec) const {
|
|||
}
|
||||
|
||||
void Rig::copyJointsFromJointData(const QVector<JointData>& jointDataVec) {
|
||||
PerformanceTimer perfTimer("copyJoints");
|
||||
PROFILE_RANGE(simulation_animation_detail, "copyJoints");
|
||||
DETAILED_PROFILE_RANGE(simulation_animation_detail, "copyJoints");
|
||||
DETAILED_PERFORMANCE_TIMER("copyJoints");
|
||||
|
||||
if (!_animSkeleton) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -135,6 +135,7 @@ static const int32_t exp2Table[1 << EXP2_TABBITS][3] = {
|
|||
|
||||
static const int IEEE754_FABS_MASK = 0x7fffffff;
|
||||
static const int IEEE754_MANT_BITS = 23;
|
||||
static const int IEEE754_EXPN_BITS = 8;
|
||||
static const int IEEE754_EXPN_BIAS = 127;
|
||||
|
||||
//
|
||||
|
@ -152,7 +153,7 @@ static inline int32_t peaklog2(float* input) {
|
|||
|
||||
// split into e and x - 1.0
|
||||
int32_t e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM;
|
||||
int32_t x = (peak << (31 - IEEE754_MANT_BITS)) & 0x7fffffff;
|
||||
int32_t x = (peak << IEEE754_EXPN_BITS) & 0x7fffffff;
|
||||
|
||||
// saturate
|
||||
if (e > 31) {
|
||||
|
@ -191,7 +192,7 @@ static inline int32_t peaklog2(float* input0, float* input1) {
|
|||
|
||||
// split into e and x - 1.0
|
||||
int32_t e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM;
|
||||
int32_t x = (peak << (31 - IEEE754_MANT_BITS)) & 0x7fffffff;
|
||||
int32_t x = (peak << IEEE754_EXPN_BITS) & 0x7fffffff;
|
||||
|
||||
// saturate
|
||||
if (e > 31) {
|
||||
|
@ -234,7 +235,7 @@ static inline int32_t peaklog2(float* input0, float* input1, float* input2, floa
|
|||
|
||||
// split into e and x - 1.0
|
||||
int32_t e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM;
|
||||
int32_t x = (peak << (31 - IEEE754_MANT_BITS)) & 0x7fffffff;
|
||||
int32_t x = (peak << IEEE754_EXPN_BITS) & 0x7fffffff;
|
||||
|
||||
// saturate
|
||||
if (e > 31) {
|
||||
|
@ -259,30 +260,30 @@ static inline int32_t peaklog2(float* input0, float* input1, float* input2, floa
|
|||
// Count Leading Zeros
|
||||
// Emulates the CLZ (ARM) and LZCNT (x86) instruction
|
||||
//
|
||||
static inline int CLZ(uint32_t x) {
|
||||
static inline int CLZ(uint32_t u) {
|
||||
|
||||
if (x == 0) {
|
||||
if (u == 0) {
|
||||
return 32;
|
||||
}
|
||||
|
||||
int e = 0;
|
||||
if (x < 0x00010000) {
|
||||
x <<= 16;
|
||||
if (u < 0x00010000) {
|
||||
u <<= 16;
|
||||
e += 16;
|
||||
}
|
||||
if (x < 0x01000000) {
|
||||
x <<= 8;
|
||||
if (u < 0x01000000) {
|
||||
u <<= 8;
|
||||
e += 8;
|
||||
}
|
||||
if (x < 0x10000000) {
|
||||
x <<= 4;
|
||||
if (u < 0x10000000) {
|
||||
u <<= 4;
|
||||
e += 4;
|
||||
}
|
||||
if (x < 0x40000000) {
|
||||
x <<= 2;
|
||||
if (u < 0x40000000) {
|
||||
u <<= 2;
|
||||
e += 2;
|
||||
}
|
||||
if (x < 0x80000000) {
|
||||
if (u < 0x80000000) {
|
||||
e += 1;
|
||||
}
|
||||
return e;
|
||||
|
@ -290,19 +291,19 @@ static inline int CLZ(uint32_t x) {
|
|||
|
||||
//
|
||||
// Compute -log2(x) for x=[0,1] in Q31, result in Q26
|
||||
// x = 0 returns 0x7fffffff
|
||||
// x < 0 undefined
|
||||
// x <= 0 returns 0x7fffffff
|
||||
//
|
||||
static inline int32_t fixlog2(int32_t x) {
|
||||
|
||||
if (x == 0) {
|
||||
if (x <= 0) {
|
||||
return 0x7fffffff;
|
||||
}
|
||||
|
||||
// split into e and x - 1.0
|
||||
int e = CLZ((uint32_t)x);
|
||||
x <<= e; // normalize to [0x80000000, 0xffffffff]
|
||||
x &= 0x7fffffff; // x - 1.0
|
||||
uint32_t u = (uint32_t)x;
|
||||
int e = CLZ(u);
|
||||
u <<= e; // normalize to [0x80000000, 0xffffffff]
|
||||
x = u & 0x7fffffff; // x - 1.0
|
||||
|
||||
int k = x >> (31 - LOG2_TABBITS);
|
||||
|
||||
|
@ -320,13 +321,18 @@ static inline int32_t fixlog2(int32_t x) {
|
|||
|
||||
//
|
||||
// Compute exp2(-x) for x=[0,32] in Q26, result in Q31
|
||||
// x < 0 undefined
|
||||
// x <= 0 returns 0x7fffffff
|
||||
//
|
||||
static inline int32_t fixexp2(int32_t x) {
|
||||
|
||||
if (x <= 0) {
|
||||
return 0x7fffffff;
|
||||
}
|
||||
|
||||
// split into e and 1.0 - x
|
||||
int e = x >> LOG2_FRACBITS;
|
||||
x = ~(x << LOG2_INTBITS) & 0x7fffffff;
|
||||
uint32_t u = (uint32_t)x;
|
||||
int e = u >> LOG2_FRACBITS;
|
||||
x = ~(u << LOG2_INTBITS) & 0x7fffffff;
|
||||
|
||||
int k = x >> (31 - EXP2_TABBITS);
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ class MonoDCBlock {
|
|||
public:
|
||||
void process(int32_t& x) {
|
||||
|
||||
x <<= 15; // scale to Q30
|
||||
x *= (1 << 15); // scale to Q30
|
||||
x -= _dcOffset; // remove DC
|
||||
_dcOffset += x >> 13; // pole = (1.0 - 2^-13) = 0.9999
|
||||
}
|
||||
|
@ -53,8 +53,8 @@ class StereoDCBlock {
|
|||
public:
|
||||
void process(int32_t& x0, int32_t& x1) {
|
||||
|
||||
x0 <<= 15;
|
||||
x1 <<= 15;
|
||||
x0 *= (1 << 15);
|
||||
x1 *= (1 << 15);
|
||||
|
||||
x0 -= _dcOffset[0];
|
||||
x1 -= _dcOffset[1];
|
||||
|
@ -71,10 +71,10 @@ class QuadDCBlock {
|
|||
public:
|
||||
void process(int32_t& x0, int32_t& x1, int32_t& x2, int32_t& x3) {
|
||||
|
||||
x0 <<= 15;
|
||||
x1 <<= 15;
|
||||
x2 <<= 15;
|
||||
x3 <<= 15;
|
||||
x0 *= (1 << 15);
|
||||
x1 *= (1 << 15);
|
||||
x2 *= (1 << 15);
|
||||
x3 *= (1 << 15);
|
||||
|
||||
x0 -= _dcOffset[0];
|
||||
x1 -= _dcOffset[1];
|
||||
|
@ -100,10 +100,10 @@ protected:
|
|||
int _histogram[NHIST] = {};
|
||||
|
||||
// peakhold
|
||||
int32_t _holdMin = 0x7fffffff;
|
||||
int32_t _holdInc = 0x7fffffff;
|
||||
uint32_t _holdMin = 0x7fffffff;
|
||||
uint32_t _holdInc = 0x7fffffff;
|
||||
uint32_t _holdMax = 0x7fffffff;
|
||||
int32_t _holdRel = 0x7fffffff;
|
||||
uint32_t _holdRel = 0x7fffffff;
|
||||
int32_t _holdPeak = 0x7fffffff;
|
||||
|
||||
// hysteresis
|
||||
|
@ -177,18 +177,23 @@ void GateImpl::setThreshold(float threshold) {
|
|||
void GateImpl::setHold(float hold) {
|
||||
|
||||
const double RELEASE = 100.0; // release = 100ms
|
||||
const double PROGHOLD = 0.100; // progressive hold = 100ms
|
||||
const double PROGHOLD = 100.0; // progressive hold = 100ms
|
||||
|
||||
// pure hold = 1 to 1000ms
|
||||
hold = MAX(hold, 1.0f);
|
||||
hold = MIN(hold, 1000.0f);
|
||||
|
||||
// compute final tc
|
||||
_holdMin = msToTc(RELEASE, _sampleRate);
|
||||
|
||||
_holdInc = (int32_t)((_holdMin - 0x7fffffff) / (PROGHOLD * _sampleRate));
|
||||
_holdInc = MIN(_holdInc, -1); // prevent 0 on long releases
|
||||
|
||||
_holdMax = 0x7fffffff - (uint32_t)(_holdInc * (double)hold/1000.0 * _sampleRate);
|
||||
// compute tc increment, to progress from 0x7fffffff to _holdMin in PROGHOLD ms
|
||||
double progSamples = PROGHOLD/1000.0 * _sampleRate;
|
||||
_holdInc = (uint32_t)((0x7fffffff - _holdMin) / progSamples);
|
||||
_holdInc = MAX(_holdInc, 1); // prevent 0 on long releases
|
||||
|
||||
// compute initial tc, to progress from _holdMax to 0x7fffffff in hold ms
|
||||
double holdSamples = (double)hold/1000.0 * _sampleRate;
|
||||
_holdMax = 0x7fffffff + (uint32_t)(_holdInc * holdSamples);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -318,8 +323,6 @@ void GateImpl::processHistogram(int numFrames) {
|
|||
|
||||
// smooth threshold update
|
||||
_threshAdapt = threshold + MULQ31((_threshAdapt - threshold), tcThreshold);
|
||||
|
||||
//printf("threshold = %0.1f\n", (_threshAdapt - (LOG2_HEADROOM_Q15 << LOG2_FRACBITS)) * -6.02f / (1 << LOG2_FRACBITS));
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -336,10 +339,8 @@ int32_t GateImpl::peakhold(int32_t peak) {
|
|||
// (_holdRel > _holdMin) progressive hold
|
||||
// (_holdRel = _holdMin) release
|
||||
|
||||
_holdRel += _holdInc; // update progressive hold
|
||||
_holdRel = MAX((uint32_t)_holdRel, (uint32_t)_holdMin); // saturate at final value
|
||||
|
||||
int32_t tc = MIN((uint32_t)_holdRel, 0x7fffffff);
|
||||
_holdRel -= _holdInc; // update progressive hold
|
||||
int32_t tc = MIN(MAX(_holdRel, _holdMin), 0x7fffffff); // saturate to [_holdMin, 0x7fffffff]
|
||||
peak += MULQ31((_holdPeak - peak), tc); // apply release
|
||||
|
||||
} else {
|
||||
|
|
|
@ -46,6 +46,10 @@ static const int STATS_FOR_STATS_PACKET_WINDOW_SECONDS = 30;
|
|||
// _currentJitterBufferFrames is updated with the time-weighted avg and the running time-weighted avg is reset.
|
||||
static const quint64 FRAMES_AVAILABLE_STAT_WINDOW_USECS = 10 * USECS_PER_SECOND;
|
||||
|
||||
// When the audio codec is switched, temporary codec mismatch is expected due to packets in-flight.
|
||||
// A SelectedAudioFormat packet is not sent until this threshold is exceeded.
|
||||
static const int MAX_MISMATCHED_AUDIO_CODEC_COUNT = 10;
|
||||
|
||||
InboundAudioStream::InboundAudioStream(int numChannels, int numFrames, int numBlocks, int numStaticJitterBlocks) :
|
||||
_ringBuffer(numChannels * numFrames, numBlocks),
|
||||
_numChannels(numChannels),
|
||||
|
@ -153,6 +157,7 @@ int InboundAudioStream::parseData(ReceivedMessage& message) {
|
|||
// If we recieved a SilentAudioFrame from our sender, we might want to drop
|
||||
// some of the samples in order to catch up to our desired jitter buffer size.
|
||||
writeDroppableSilentFrames(networkFrames);
|
||||
|
||||
} else {
|
||||
// note: PCM and no codec are identical
|
||||
bool selectedPCM = _selectedCodecName == "pcm" || _selectedCodecName == "";
|
||||
|
@ -160,20 +165,33 @@ int InboundAudioStream::parseData(ReceivedMessage& message) {
|
|||
if (codecInPacket == _selectedCodecName || (packetPCM && selectedPCM)) {
|
||||
auto afterProperties = message.readWithoutCopy(message.getBytesLeftToRead());
|
||||
parseAudioData(message.getType(), afterProperties);
|
||||
_mismatchedAudioCodecCount = 0;
|
||||
|
||||
} else {
|
||||
qDebug(audio) << "Codec mismatch: expected" << _selectedCodecName << "got" << codecInPacket << "writing silence";
|
||||
_mismatchedAudioCodecCount++;
|
||||
qDebug(audio) << "Codec mismatch: expected" << _selectedCodecName << "got" << codecInPacket;
|
||||
|
||||
// Since the data in the stream is using a codec that we aren't prepared for,
|
||||
// we need to let the codec know that we don't have data for it, this will
|
||||
// allow the codec to interpolate missing data and produce a fade to silence.
|
||||
lostAudioData(1);
|
||||
|
||||
// inform others of the mismatch
|
||||
auto sendingNode = DependencyManager::get<NodeList>()->nodeWithUUID(message.getSourceID());
|
||||
if (sendingNode) {
|
||||
emit mismatchedAudioCodec(sendingNode, _selectedCodecName, codecInPacket);
|
||||
if (packetPCM) {
|
||||
// If there are PCM packets in-flight after the codec is changed, use them.
|
||||
auto afterProperties = message.readWithoutCopy(message.getBytesLeftToRead());
|
||||
_ringBuffer.writeData(afterProperties.data(), afterProperties.size());
|
||||
} else {
|
||||
// Since the data in the stream is using a codec that we aren't prepared for,
|
||||
// we need to let the codec know that we don't have data for it, this will
|
||||
// allow the codec to interpolate missing data and produce a fade to silence.
|
||||
lostAudioData(1);
|
||||
}
|
||||
|
||||
if (_mismatchedAudioCodecCount > MAX_MISMATCHED_AUDIO_CODEC_COUNT) {
|
||||
_mismatchedAudioCodecCount = 0;
|
||||
|
||||
// inform others of the mismatch
|
||||
auto sendingNode = DependencyManager::get<NodeList>()->nodeWithUUID(message.getSourceID());
|
||||
if (sendingNode) {
|
||||
emit mismatchedAudioCodec(sendingNode, _selectedCodecName, codecInPacket);
|
||||
qDebug(audio) << "Codec mismatch threshold exceeded, SelectedAudioFormat(" << _selectedCodecName << " ) sent";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -186,6 +186,7 @@ protected:
|
|||
CodecPluginPointer _codec;
|
||||
QString _selectedCodecName;
|
||||
Decoder* _decoder { nullptr };
|
||||
int _mismatchedAudioCodecCount { 0 };
|
||||
};
|
||||
|
||||
float calculateRepeatedFrameFadeFactor(int indexOfRepeat);
|
||||
|
|