diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index 64f4aa6821..d874100ca2 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -453,6 +453,13 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node) // or that somehow we haven't sent if (lastSeqToReceiver == lastSeqFromSender && lastSeqToReceiver != 0) { ++numAvatarsHeldBack; + + // BUGZ-781 verbose debugging: + auto usecLastTimeSent = destinationNodeData->getLastOtherAvatarEncodeTime(sourceAvatarNodeData->getNodeLocalID()); + if (usecLastTimeSent != 0 && startIgnoreCalculation - usecLastTimeSent > 10 * USECS_PER_SECOND) { + qCDebug(avatars) << "Not sent avatar" << *sourceAvatarNode << "to Node" << *destinationNode << "in > 10 s"; + } + sendAvatar = false; } else if (lastSeqFromSender == 0) { // We have have not yet received any data about this avatar. Ignore it for now diff --git a/cmake/macros/AutoScribeShader.cmake b/cmake/macros/AutoScribeShader.cmake index c5bb2b4054..20aa334134 100755 --- a/cmake/macros/AutoScribeShader.cmake +++ b/cmake/macros/AutoScribeShader.cmake @@ -66,6 +66,9 @@ macro(AUTOSCRIBE_PLATFORM_SHADER) list(APPEND SHADER_GEN_LINE ${TEMP_PATH}) file(RELATIVE_PATH TEMP_PATH ${CMAKE_SOURCE_DIR} ${AUTOSCRIBE_OUTPUT_FILE}) list(APPEND SHADER_GEN_LINE ${TEMP_PATH}) + if (NOT("${DEFINES}" STREQUAL "")) + list(APPEND SHADER_GEN_LINE "defines:${DEFINES}") + endif() list(APPEND SHADER_GEN_LINE ${AUTOSCRIBE_SHADER_SEEN_LIBS}) string(CONCAT AUTOSCRIBE_SHADERGEN_COMMANDS "${AUTOSCRIBE_SHADERGEN_COMMANDS}" "${SHADER_GEN_LINE}\n") endmacro() @@ -108,6 +111,10 @@ macro(AUTOSCRIBE_SHADER) set(SHADER_TYPE geom) endif() + if (NOT("${DEFINES}" STREQUAL "")) + string(CONCAT SHADER_NAME "${SHADER_NAME}" "_${DEFINES}") + endif() + set(SCRIBE_ARGS -D GLPROFILE ${GLPROFILE} -T ${SHADER_TYPE} ${SCRIBE_INCLUDES} ) # SHADER_SCRIBED -> the output of scribe @@ -135,11 +142,78 @@ macro(AUTOSCRIBE_SHADER) endif() endif() - string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "${SHADER_NAME} = ${SHADER_COUNT},\n") + string(CONCAT SHADER_LIST "${SHADER_LIST}" "${SHADER_NAME} = ${SHADER_COUNT},\n") string(CONCAT SHADER_SHADERS_ARRAY "${SHADER_SHADERS_ARRAY}" "${SHADER_COUNT},\n") MATH(EXPR SHADER_COUNT "${SHADER_COUNT}+1") endmacro() +# This function takes in the list of defines, which would look like: +# (normalmap;translucent:f)/shadow;deformed:v +# and handles parentheses and slashes, producing the semicolon-separated final list of all combinations, which in that case will look like: +# normalmap;translucent:f;normalmap_translucent:f;shadow;normalmap_deformed:v;translucent:f_deformed:v;normalmap_translucent:f_deformed:v;shadow_deformed:v +function(GENERATE_DEFINES_LIST_HELPER INPUT_LIST RETURN_LIST) + # This while loop handles parentheses, looking for matching ( and ) and then calling GENERATE_DEFINES_LIST_HELPER recursively on the text in between + string(LENGTH "${INPUT_LIST}" STR_LENGTH) + set(OPEN_INDEX -1) + set(STR_INDEX 0) + set(NESTED_DEPTH 0) + while ("${STR_INDEX}" LESS "${STR_LENGTH}") + string(SUBSTRING "${INPUT_LIST}" ${STR_INDEX} 1 CURRENT_CHAR) + + if (("${CURRENT_CHAR}" STREQUAL "(") AND (OPEN_INDEX EQUAL -1)) + set(OPEN_INDEX ${STR_INDEX}) + MATH(EXPR STR_INDEX "${STR_INDEX}+1") + continue() + elseif (("${CURRENT_CHAR}" STREQUAL "(") AND NOT(OPEN_INDEX EQUAL -1)) + MATH(EXPR NESTED_DEPTH "${NESTED_DEPTH}+1") + MATH(EXPR STR_INDEX "${STR_INDEX}+1") + continue() + elseif (("${CURRENT_CHAR}" STREQUAL ")") AND NOT(OPEN_INDEX EQUAL -1) AND (NESTED_DEPTH GREATER 0)) + MATH(EXPR NESTED_DEPTH "${NESTED_DEPTH}-1") + MATH(EXPR STR_INDEX "${STR_INDEX}+1") + continue() + elseif (("${CURRENT_CHAR}" STREQUAL ")") AND NOT(OPEN_INDEX EQUAL -1) AND (NESTED_DEPTH EQUAL 0)) + MATH(EXPR OPEN_INDEX "${OPEN_INDEX}+1") + MATH(EXPR SUBSTR_LENGTH "${STR_INDEX}-${OPEN_INDEX}") + string(SUBSTRING "${INPUT_LIST}" ${OPEN_INDEX} ${SUBSTR_LENGTH} GROUP_STR) + GENERATE_DEFINES_LIST_HELPER("${GROUP_STR}" EXPANDED_GROUP_LIST) + string(REPLACE ";" "/" EXPANDED_GROUP_LIST "${EXPANDED_GROUP_LIST}") + string(REPLACE "(${GROUP_STR})" "${EXPANDED_GROUP_LIST}" INPUT_LIST "${INPUT_LIST}") + MATH(EXPR STR_INDEX "${OPEN_INDEX}-1") + set(OPEN_INDEX -1) + string(LENGTH "${INPUT_LIST}" STR_LENGTH) + continue() + endif() + + MATH(EXPR STR_INDEX "${STR_INDEX}+1") + endwhile() + + # Here we handle the base case, the recursive case, and slashes + list(LENGTH INPUT_LIST NUM_DEFINES) + if (NUM_DEFINES EQUAL 1) + string(REPLACE "/" ";" INPUT_LIST "${INPUT_LIST}") + set(${RETURN_LIST} ${INPUT_LIST} PARENT_SCOPE) + elseif (NUM_DEFINES GREATER 1) + list(GET INPUT_LIST 0 CURRENT_DEFINES) + string(REPLACE "/" ";" CURRENT_DEFINES "${CURRENT_DEFINES}") + list(REMOVE_AT INPUT_LIST 0) + GENERATE_DEFINES_LIST_HELPER("${INPUT_LIST}" REMAINING_DEFINES_LIST) + set(TO_RETURN_LIST "${CURRENT_DEFINES}") + foreach(REMAINING_DEFINES ${REMAINING_DEFINES_LIST}) + list(APPEND TO_RETURN_LIST "${REMAINING_DEFINES}") + foreach(CURRENT_DEFINE ${CURRENT_DEFINES}) + list(APPEND TO_RETURN_LIST "${CURRENT_DEFINE}_${REMAINING_DEFINES}") + endforeach() + endforeach() + set(${RETURN_LIST} ${TO_RETURN_LIST} PARENT_SCOPE) + endif() +endfunction() + +macro(GENERATE_DEFINES_LIST) + set(DEFINES_LIST "") + GENERATE_DEFINES_LIST_HELPER("${ARGV0}" DEFINES_LIST) +endmacro() + macro(AUTOSCRIBE_SHADER_LIB) if (NOT ("${TARGET_NAME}" STREQUAL "shaders")) message(FATAL_ERROR "AUTOSCRIBE_SHADER_LIB can only be used by the shaders library") @@ -164,24 +238,24 @@ macro(AUTOSCRIBE_SHADER_LIB) if (SHADER_VERTEX_FILES) source_group("${SHADER_LIB}/Vertex" FILES ${SHADER_VERTEX_FILES}) list(APPEND ALL_SCRIBE_SHADERS ${SHADER_VERTEX_FILES}) - string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "namespace vertex { enum {\n") - foreach(SHADER_FILE ${SHADER_VERTEX_FILES}) + set(SHADER_LIST "namespace vertex { enum {\n") + foreach(SHADER_FILE ${SHADER_VERTEX_FILES}) AUTOSCRIBE_SHADER(${ALL_SHADER_HEADERS}) endforeach() - string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "}; } // vertex \n") + set(VERTEX_ENUMS "${SHADER_LIST}") endif() file(GLOB_RECURSE SHADER_FRAGMENT_FILES ${SRC_FOLDER}/*.slf) if (SHADER_FRAGMENT_FILES) source_group("${SHADER_LIB}/Fragment" FILES ${SHADER_FRAGMENT_FILES}) list(APPEND ALL_SCRIBE_SHADERS ${SHADER_FRAGMENT_FILES}) - string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "namespace fragment { enum {\n") - foreach(SHADER_FILE ${SHADER_FRAGMENT_FILES}) + set(SHADER_LIST "namespace fragment { enum {\n") + foreach(SHADER_FILE ${SHADER_FRAGMENT_FILES}) AUTOSCRIBE_SHADER(${ALL_SHADER_HEADERS}) endforeach() - string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "}; } // fragment \n") + set(FRAGMENT_ENUMS "${SHADER_LIST}") endif() - + # FIXME add support for geometry, compute and tesselation shaders #file(GLOB_RECURSE SHADER_GEOMETRY_FILES ${SRC_FOLDER}/*.slg) #file(GLOB_RECURSE SHADER_COMPUTE_FILES ${SRC_FOLDER}/*.slc) @@ -191,13 +265,14 @@ macro(AUTOSCRIBE_SHADER_LIB) if (SHADER_PROGRAM_FILES) source_group("${SHADER_LIB}/Program" FILES ${SHADER_PROGRAM_FILES}) list(APPEND ALL_SCRIBE_SHADERS ${SHADER_PROGRAM_FILES}) - string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "namespace program { enum {\n") + set(PROGRAM_ENUMS "namespace program { enum {\n") foreach(PROGRAM_FILE ${SHADER_PROGRAM_FILES}) get_filename_component(PROGRAM_NAME ${PROGRAM_FILE} NAME_WE) - set(AUTOSCRIBE_PROGRAM_FRAGMENT ${PROGRAM_NAME}) + get_filename_component(PROGRAM_FOLDER ${PROGRAM_FILE} DIRECTORY) file(READ ${PROGRAM_FILE} PROGRAM_CONFIG) set(AUTOSCRIBE_PROGRAM_VERTEX ${PROGRAM_NAME}) set(AUTOSCRIBE_PROGRAM_FRAGMENT ${PROGRAM_NAME}) + set(AUTOSCRIBE_PROGRAM_DEFINES "") if (NOT("${PROGRAM_CONFIG}" STREQUAL "")) string(REGEX MATCH ".*VERTEX +([_\\:A-Z0-9a-z]+)" MVERT ${PROGRAM_CONFIG}) @@ -208,6 +283,12 @@ macro(AUTOSCRIBE_SHADER_LIB) if (CMAKE_MATCH_1) set(AUTOSCRIBE_PROGRAM_FRAGMENT ${CMAKE_MATCH_1}) endif() + string(REGEX MATCH ".*DEFINES +([a-zA-Z\(\)/: ]+)" MDEF ${PROGRAM_CONFIG}) + if (CMAKE_MATCH_1) + set(AUTOSCRIBE_PROGRAM_DEFINES ${CMAKE_MATCH_1}) + string(TOLOWER AUTOSCRIBE_PROGRAM_DEFINES "${AUTOSCRIBE_PROGRAM_DEFINES}") + string(REGEX REPLACE " +" ";" AUTOSCRIBE_PROGRAM_DEFINES "${AUTOSCRIBE_PROGRAM_DEFINES}") + endif() endif() if (NOT (${AUTOSCRIBE_PROGRAM_VERTEX} MATCHES ".*::.*")) @@ -216,12 +297,82 @@ macro(AUTOSCRIBE_SHADER_LIB) if (NOT (${AUTOSCRIBE_PROGRAM_FRAGMENT} MATCHES ".*::.*")) set(AUTOSCRIBE_PROGRAM_FRAGMENT "fragment::${AUTOSCRIBE_PROGRAM_FRAGMENT}") endif() + string(REGEX REPLACE ".*::" "" VERTEX_NAME "${AUTOSCRIBE_PROGRAM_VERTEX}") + string(REGEX REPLACE ".*::" "" FRAGMENT_NAME "${AUTOSCRIBE_PROGRAM_FRAGMENT}") - set(PROGRAM_ENTRY "${PROGRAM_NAME} = (${AUTOSCRIBE_PROGRAM_VERTEX} << 16) | ${AUTOSCRIBE_PROGRAM_FRAGMENT},\n") - string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "${PROGRAM_ENTRY}") + GENERATE_DEFINES_LIST("${AUTOSCRIBE_PROGRAM_DEFINES}") + + string(CONCAT PROGRAM_ENUMS "${PROGRAM_ENUMS}" "${PROGRAM_NAME} = (${AUTOSCRIBE_PROGRAM_VERTEX} << 16) | ${AUTOSCRIBE_PROGRAM_FRAGMENT},\n") string(CONCAT SHADER_PROGRAMS_ARRAY "${SHADER_PROGRAMS_ARRAY} ${SHADER_NAMESPACE}::program::${PROGRAM_NAME},\n") + + foreach(DEFINES ${DEFINES_LIST}) + set(ORIG_DEFINES "${DEFINES}") + + # Below here we handle :v and :f. The program name includes both, but the vertex and fragment names + # remove the elements with :f and :v respectively, and only have to call AUTOSCRIBE_SHADER if they don't have those + # (because the shaders without them will have already been generated) + string(REPLACE ":v" "" VERTEX_DEFINES "${ORIG_DEFINES}") + string(FIND "${ORIG_DEFINES}" ":f" HAS_FRAGMENT) + if (HAS_FRAGMENT EQUAL -1) + set(DEFINES "${VERTEX_DEFINES}") + set(SHADER_LIST "") + set(SHADER_FILE "${PROGRAM_FOLDER}/${VERTEX_NAME}.slv") + if (NOT EXISTS "${SHADER_FILE}") + set(SHADER_FILE "${PROGRAM_FOLDER}/../${VERTEX_NAME}.slv") + endif() + find_file(SHADER_FILE "" PATHS "${PROGRAM_FOLDER}" PATH_SUFFIXES ".." NO_DEFAULT_PATH) + AUTOSCRIBE_SHADER(${ALL_SHADER_HEADERS}) + string(CONCAT VERTEX_ENUMS "${VERTEX_ENUMS}" "${SHADER_LIST}") + else() + string(REGEX REPLACE "_*[^_]*:f" "" VERTEX_DEFINES "${VERTEX_DEFINES}") + endif() + + if (NOT("${VERTEX_DEFINES}" STREQUAL "") AND NOT("${VERTEX_DEFINES}" MATCHES "^_.*")) + set(VERTEX_DEFINES "_${VERTEX_DEFINES}") + endif() + + string(REPLACE ":f" "" FRAGMENT_DEFINES "${ORIG_DEFINES}") + string(FIND "${ORIG_DEFINES}" ":v" HAS_VERTEX) + if (HAS_VERTEX EQUAL -1) + set(DEFINES "${FRAGMENT_DEFINES}") + set(SHADER_LIST "") + set(SHADER_FILE "${PROGRAM_FOLDER}/${FRAGMENT_NAME}.slf") + if (NOT EXISTS "${SHADER_FILE}") + set(SHADER_FILE "${PROGRAM_FOLDER}/../${FRAGMENT_NAME}.slf") + endif() + AUTOSCRIBE_SHADER(${ALL_SHADER_HEADERS}) + string(CONCAT FRAGMENT_ENUMS "${FRAGMENT_ENUMS}" "${SHADER_LIST}") + else() + string(REGEX REPLACE "_*[^_]*:v" "" FRAGMENT_DEFINES "${FRAGMENT_DEFINES}") + endif() + + if (NOT("${FRAGMENT_DEFINES}" STREQUAL "") AND NOT("${FRAGMENT_DEFINES}" MATCHES "^_.*")) + set(FRAGMENT_DEFINES "_${FRAGMENT_DEFINES}") + endif() + + string(REGEX REPLACE ":(f|v)" "" PROGRAM_DEFINES "${ORIG_DEFINES}") + + if (NOT("${PROGRAM_DEFINES}" STREQUAL "")) + string(CONCAT PROGRAM_ENUMS "${PROGRAM_ENUMS}" "${PROGRAM_NAME}_${PROGRAM_DEFINES} = (${AUTOSCRIBE_PROGRAM_VERTEX}${VERTEX_DEFINES} << 16) | ${AUTOSCRIBE_PROGRAM_FRAGMENT}${FRAGMENT_DEFINES},\n") + string(CONCAT SHADER_PROGRAMS_ARRAY "${SHADER_PROGRAMS_ARRAY} ${SHADER_NAMESPACE}::program::${PROGRAM_NAME}_${PROGRAM_DEFINES},\n") + endif() + endforeach() endforeach() - string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "}; } // program \n") + endif() + + if (SHADER_VERTEX_FILES) + string(CONCAT VERTEX_ENUMS "${VERTEX_ENUMS}" "}; } // vertex \n") + string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "${VERTEX_ENUMS}") + endif() + + if (SHADER_FRAGMENT_FILES) + string(CONCAT FRAGMENT_ENUMS "${FRAGMENT_ENUMS}" "}; } // fragment \n") + string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "${FRAGMENT_ENUMS}") + endif() + + if (SHADER_PROGRAM_FILES) + string(CONCAT PROGRAM_ENUMS "${PROGRAM_ENUMS}" "}; } // program \n") + string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "${PROGRAM_ENUMS}") endif() # Finish the shader enums diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index 6aaa348f6c..09a0446468 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -121,12 +121,13 @@ void DomainGatekeeper::processConnectRequestPacket(QSharedPointersetNodeInterestSet(safeInterestSet); nodeData->setPlaceName(nodeConnection.placeName); + QMetaEnum metaEnum = QMetaEnum::fromType(); qDebug() << "Allowed connection from node" << uuidStringWithoutCurlyBraces(node->getUUID()) << "on" << message->getSenderSockAddr() << "with MAC" << nodeConnection.hardwareAddress << "and machine fingerprint" << nodeConnection.machineFingerprint << "user" << username - << "reason" << QString(nodeConnection.connectReason ? "SilentDomainDisconnect" : "Connect") + << "reason" << QString(metaEnum.valueToKey(nodeConnection.connectReason)) << "previous connection uptime" << nodeConnection.previousConnectionUpTime/USECS_PER_MSEC << "msec" << "sysinfo" << nodeConnection.SystemInfo; diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index c3a4a94c7c..b7c723ab48 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -2498,7 +2498,7 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url return true; } else if (allNodesDeleteRegex.indexIn(url.path()) != -1) { qDebug() << "Received request to kill all nodes."; - nodeList->eraseAllNodes(); + nodeList->eraseAllNodes(url.path()); return true; } diff --git a/interface/resources/avatar/animations/fly.fbx b/interface/resources/avatar/animations/fly.fbx index 4a855032f9..5d8fcce23b 100644 Binary files a/interface/resources/avatar/animations/fly.fbx and b/interface/resources/avatar/animations/fly.fbx differ diff --git a/interface/resources/avatar/animations/idle.fbx b/interface/resources/avatar/animations/idle.fbx index 88c79185a1..a2cbb9b43b 100644 Binary files a/interface/resources/avatar/animations/idle.fbx and b/interface/resources/avatar/animations/idle.fbx differ diff --git a/interface/resources/avatar/animations/idle02.fbx b/interface/resources/avatar/animations/idle02.fbx new file mode 100644 index 0000000000..c18162dda1 Binary files /dev/null and b/interface/resources/avatar/animations/idle02.fbx differ diff --git a/interface/resources/avatar/animations/idle03.fbx b/interface/resources/avatar/animations/idle03.fbx new file mode 100644 index 0000000000..5349c49a31 Binary files /dev/null and b/interface/resources/avatar/animations/idle03.fbx differ diff --git a/interface/resources/avatar/animations/idle_lookaround01.fbx b/interface/resources/avatar/animations/idle04.fbx similarity index 59% rename from interface/resources/avatar/animations/idle_lookaround01.fbx rename to interface/resources/avatar/animations/idle04.fbx index fbea065713..c0676a7980 100644 Binary files a/interface/resources/avatar/animations/idle_lookaround01.fbx and b/interface/resources/avatar/animations/idle04.fbx differ diff --git a/interface/resources/avatar/animations/idleWS.fbx b/interface/resources/avatar/animations/idleWS.fbx deleted file mode 100644 index e730165012..0000000000 Binary files a/interface/resources/avatar/animations/idleWS.fbx and /dev/null differ diff --git a/interface/resources/avatar/animations/idleWS_all.fbx b/interface/resources/avatar/animations/idleWS_all.fbx index f9ac3dacfb..3605ecfcf4 100644 Binary files a/interface/resources/avatar/animations/idleWS_all.fbx and b/interface/resources/avatar/animations/idleWS_all.fbx differ diff --git a/interface/resources/avatar/animations/idle_LFF_all.fbx b/interface/resources/avatar/animations/idle_LFF_all.fbx index 6904773cd5..0344a270a7 100644 Binary files a/interface/resources/avatar/animations/idle_LFF_all.fbx and b/interface/resources/avatar/animations/idle_LFF_all.fbx differ diff --git a/interface/resources/avatar/animations/idle_RFF_all.fbx b/interface/resources/avatar/animations/idle_RFF_all.fbx index 77ea06dc70..8aec6a33c0 100644 Binary files a/interface/resources/avatar/animations/idle_RFF_all.fbx and b/interface/resources/avatar/animations/idle_RFF_all.fbx differ diff --git a/interface/resources/avatar/animations/idle_once_armstretch.fbx b/interface/resources/avatar/animations/idle_once_armstretch.fbx deleted file mode 100644 index 23eeed3b26..0000000000 Binary files a/interface/resources/avatar/animations/idle_once_armstretch.fbx and /dev/null differ diff --git a/interface/resources/avatar/animations/idle_once_bigstretch.fbx b/interface/resources/avatar/animations/idle_once_bigstretch.fbx deleted file mode 100644 index 5e4731279f..0000000000 Binary files a/interface/resources/avatar/animations/idle_once_bigstretch.fbx and /dev/null differ diff --git a/interface/resources/avatar/animations/idle_once_checkwatch.fbx b/interface/resources/avatar/animations/idle_once_checkwatch.fbx deleted file mode 100644 index 888d0bcbfc..0000000000 Binary files a/interface/resources/avatar/animations/idle_once_checkwatch.fbx and /dev/null differ diff --git a/interface/resources/avatar/animations/idle_once_fidget.fbx b/interface/resources/avatar/animations/idle_once_fidget.fbx new file mode 100644 index 0000000000..2270614901 Binary files /dev/null and b/interface/resources/avatar/animations/idle_once_fidget.fbx differ diff --git a/interface/resources/avatar/animations/idle_once_headtilt.fbx b/interface/resources/avatar/animations/idle_once_headtilt.fbx index 21d1bc43c8..eeae4604aa 100644 Binary files a/interface/resources/avatar/animations/idle_once_headtilt.fbx and b/interface/resources/avatar/animations/idle_once_headtilt.fbx differ diff --git a/interface/resources/avatar/animations/idle_once_lookaround.fbx b/interface/resources/avatar/animations/idle_once_lookaround.fbx index 15be33092c..b638191654 100644 Binary files a/interface/resources/avatar/animations/idle_once_lookaround.fbx and b/interface/resources/avatar/animations/idle_once_lookaround.fbx differ diff --git a/interface/resources/avatar/animations/idle_once_lookleftright.fbx b/interface/resources/avatar/animations/idle_once_lookleftright.fbx new file mode 100644 index 0000000000..72aee7931e Binary files /dev/null and b/interface/resources/avatar/animations/idle_once_lookleftright.fbx differ diff --git a/interface/resources/avatar/animations/idle_once_neckstretch.fbx b/interface/resources/avatar/animations/idle_once_neckstretch.fbx index 3968b96615..5ee4a99d65 100644 Binary files a/interface/resources/avatar/animations/idle_once_neckstretch.fbx and b/interface/resources/avatar/animations/idle_once_neckstretch.fbx differ diff --git a/interface/resources/avatar/animations/idle_once_shiftheelpivot.fbx b/interface/resources/avatar/animations/idle_once_shiftheelpivot.fbx new file mode 100644 index 0000000000..073b4343aa Binary files /dev/null and b/interface/resources/avatar/animations/idle_once_shiftheelpivot.fbx differ diff --git a/interface/resources/avatar/animations/idle_once_slownod.fbx b/interface/resources/avatar/animations/idle_once_slownod.fbx index ad4f4e17bf..7a27add7bf 100644 Binary files a/interface/resources/avatar/animations/idle_once_slownod.fbx and b/interface/resources/avatar/animations/idle_once_slownod.fbx differ diff --git a/interface/resources/avatar/animations/jog_bwd.fbx b/interface/resources/avatar/animations/jog_bwd.fbx index 479392d44c..b3eb8c919d 100644 Binary files a/interface/resources/avatar/animations/jog_bwd.fbx and b/interface/resources/avatar/animations/jog_bwd.fbx differ diff --git a/interface/resources/avatar/animations/jog_fwd.fbx b/interface/resources/avatar/animations/jog_fwd.fbx index f389fea364..9d38caacab 100644 Binary files a/interface/resources/avatar/animations/jog_fwd.fbx and b/interface/resources/avatar/animations/jog_fwd.fbx differ diff --git a/interface/resources/avatar/animations/jog_left.fbx b/interface/resources/avatar/animations/jog_left.fbx index 88600005b9..7732050201 100644 Binary files a/interface/resources/avatar/animations/jog_left.fbx and b/interface/resources/avatar/animations/jog_left.fbx differ diff --git a/interface/resources/avatar/animations/jog_right.fbx b/interface/resources/avatar/animations/jog_right.fbx new file mode 100644 index 0000000000..9b419b6eec Binary files /dev/null and b/interface/resources/avatar/animations/jog_right.fbx differ diff --git a/interface/resources/avatar/animations/jump_in_air.fbx b/interface/resources/avatar/animations/jump_in_air.fbx deleted file mode 100644 index 2e6ad32f4f..0000000000 Binary files a/interface/resources/avatar/animations/jump_in_air.fbx and /dev/null differ diff --git a/interface/resources/avatar/animations/jump_land.fbx b/interface/resources/avatar/animations/jump_land.fbx deleted file mode 100644 index f057c80085..0000000000 Binary files a/interface/resources/avatar/animations/jump_land.fbx and /dev/null differ diff --git a/interface/resources/avatar/animations/jump_running_launch_land.fbx b/interface/resources/avatar/animations/jump_running_launch_land.fbx deleted file mode 100644 index ad922d948e..0000000000 Binary files a/interface/resources/avatar/animations/jump_running_launch_land.fbx and /dev/null differ diff --git a/interface/resources/avatar/animations/jump_running_launch_land_all.fbx b/interface/resources/avatar/animations/jump_running_launch_land_all.fbx new file mode 100644 index 0000000000..71dae6bcc5 Binary files /dev/null and b/interface/resources/avatar/animations/jump_running_launch_land_all.fbx differ diff --git a/interface/resources/avatar/animations/jump_standing_apex.fbx b/interface/resources/avatar/animations/jump_standing_apex.fbx deleted file mode 100644 index 53b79758aa..0000000000 Binary files a/interface/resources/avatar/animations/jump_standing_apex.fbx and /dev/null differ diff --git a/interface/resources/avatar/animations/jump_standing_apex_all.fbx b/interface/resources/avatar/animations/jump_standing_apex_all.fbx new file mode 100644 index 0000000000..5d5873c39a Binary files /dev/null and b/interface/resources/avatar/animations/jump_standing_apex_all.fbx differ diff --git a/interface/resources/avatar/animations/jump_standing_land.fbx b/interface/resources/avatar/animations/jump_standing_land.fbx deleted file mode 100644 index aaeeb186fc..0000000000 Binary files a/interface/resources/avatar/animations/jump_standing_land.fbx and /dev/null differ diff --git a/interface/resources/avatar/animations/jump_standing_land_settle.fbx b/interface/resources/avatar/animations/jump_standing_land_settle.fbx deleted file mode 100644 index 1a11781e22..0000000000 Binary files a/interface/resources/avatar/animations/jump_standing_land_settle.fbx and /dev/null differ diff --git a/interface/resources/avatar/animations/jump_standing_land_settle_all.fbx b/interface/resources/avatar/animations/jump_standing_land_settle_all.fbx new file mode 100644 index 0000000000..ef8e83be34 Binary files /dev/null and b/interface/resources/avatar/animations/jump_standing_land_settle_all.fbx differ diff --git a/interface/resources/avatar/animations/jump_standing_launch.fbx b/interface/resources/avatar/animations/jump_standing_launch.fbx deleted file mode 100644 index 06479c8885..0000000000 Binary files a/interface/resources/avatar/animations/jump_standing_launch.fbx and /dev/null differ diff --git a/interface/resources/avatar/animations/jump_standing_launch_all.fbx b/interface/resources/avatar/animations/jump_standing_launch_all.fbx new file mode 100644 index 0000000000..e10e428579 Binary files /dev/null and b/interface/resources/avatar/animations/jump_standing_launch_all.fbx differ diff --git a/interface/resources/avatar/animations/jump_standing_takeoff.fbx b/interface/resources/avatar/animations/jump_standing_takeoff.fbx deleted file mode 100644 index 5fc6befdd0..0000000000 Binary files a/interface/resources/avatar/animations/jump_standing_takeoff.fbx and /dev/null differ diff --git a/interface/resources/avatar/animations/jump_takeoff.fbx b/interface/resources/avatar/animations/jump_takeoff.fbx deleted file mode 100644 index 3976725676..0000000000 Binary files a/interface/resources/avatar/animations/jump_takeoff.fbx and /dev/null differ diff --git a/interface/resources/avatar/animations/run_bwd.fbx b/interface/resources/avatar/animations/run_bwd.fbx index 62f49c9729..60ade1f2ac 100644 Binary files a/interface/resources/avatar/animations/run_bwd.fbx and b/interface/resources/avatar/animations/run_bwd.fbx differ diff --git a/interface/resources/avatar/animations/run_fast_fwd.fbx b/interface/resources/avatar/animations/run_fast_fwd.fbx new file mode 100644 index 0000000000..cb964d57d8 Binary files /dev/null and b/interface/resources/avatar/animations/run_fast_fwd.fbx differ diff --git a/interface/resources/avatar/animations/run_fast_left.fbx b/interface/resources/avatar/animations/run_fast_left.fbx new file mode 100644 index 0000000000..5078d0cb22 Binary files /dev/null and b/interface/resources/avatar/animations/run_fast_left.fbx differ diff --git a/interface/resources/avatar/animations/run_fast_right.fbx b/interface/resources/avatar/animations/run_fast_right.fbx new file mode 100644 index 0000000000..ddf081bef6 Binary files /dev/null and b/interface/resources/avatar/animations/run_fast_right.fbx differ diff --git a/interface/resources/avatar/animations/run_fwd.fbx b/interface/resources/avatar/animations/run_fwd.fbx deleted file mode 100644 index f28f9e0569..0000000000 Binary files a/interface/resources/avatar/animations/run_fwd.fbx and /dev/null differ diff --git a/interface/resources/avatar/animations/settle_to_idle.fbx b/interface/resources/avatar/animations/settle_to_idle.fbx deleted file mode 100644 index fba4305e9a..0000000000 Binary files a/interface/resources/avatar/animations/settle_to_idle.fbx and /dev/null differ diff --git a/interface/resources/avatar/animations/settle_to_idle_small.fbx b/interface/resources/avatar/animations/settle_to_idle_small.fbx new file mode 100644 index 0000000000..3d79d1930c Binary files /dev/null and b/interface/resources/avatar/animations/settle_to_idle_small.fbx differ diff --git a/interface/resources/avatar/animations/side_step_left.fbx b/interface/resources/avatar/animations/side_step_left.fbx index ef8cbe0a5c..b74fe9074a 100644 Binary files a/interface/resources/avatar/animations/side_step_left.fbx and b/interface/resources/avatar/animations/side_step_left.fbx differ diff --git a/interface/resources/avatar/animations/side_step_left_fast.fbx b/interface/resources/avatar/animations/side_step_left_fast.fbx index af71a46bb5..f4c997345f 100644 Binary files a/interface/resources/avatar/animations/side_step_left_fast.fbx and b/interface/resources/avatar/animations/side_step_left_fast.fbx differ diff --git a/interface/resources/avatar/animations/side_step_left_fast02.fbx b/interface/resources/avatar/animations/side_step_left_fast02.fbx deleted file mode 100644 index 9064b35d37..0000000000 Binary files a/interface/resources/avatar/animations/side_step_left_fast02.fbx and /dev/null differ diff --git a/interface/resources/avatar/animations/side_step_right.fbx b/interface/resources/avatar/animations/side_step_right.fbx deleted file mode 100644 index 6404657741..0000000000 Binary files a/interface/resources/avatar/animations/side_step_right.fbx and /dev/null differ diff --git a/interface/resources/avatar/animations/side_step_short_left.fbx b/interface/resources/avatar/animations/side_step_short_left.fbx index f236f30c31..8f55364b17 100644 Binary files a/interface/resources/avatar/animations/side_step_short_left.fbx and b/interface/resources/avatar/animations/side_step_short_left.fbx differ diff --git a/interface/resources/avatar/animations/side_step_short_right.fbx b/interface/resources/avatar/animations/side_step_short_right.fbx deleted file mode 100644 index df074c17e0..0000000000 Binary files a/interface/resources/avatar/animations/side_step_short_right.fbx and /dev/null differ diff --git a/interface/resources/avatar/animations/side_strafe_left.fbx b/interface/resources/avatar/animations/side_strafe_left.fbx deleted file mode 100644 index 61c3ba7b32..0000000000 Binary files a/interface/resources/avatar/animations/side_strafe_left.fbx and /dev/null differ diff --git a/interface/resources/avatar/animations/side_strafe_left02.fbx b/interface/resources/avatar/animations/side_strafe_left02.fbx deleted file mode 100644 index e9bc801997..0000000000 Binary files a/interface/resources/avatar/animations/side_strafe_left02.fbx and /dev/null differ diff --git a/interface/resources/avatar/animations/sitting.fbx b/interface/resources/avatar/animations/sitting.fbx deleted file mode 100644 index dfb51afb66..0000000000 Binary files a/interface/resources/avatar/animations/sitting.fbx and /dev/null differ diff --git a/interface/resources/avatar/animations/sitting_idle.fbx b/interface/resources/avatar/animations/sitting_idle.fbx deleted file mode 100644 index ee03d942cd..0000000000 Binary files a/interface/resources/avatar/animations/sitting_idle.fbx and /dev/null differ diff --git a/interface/resources/avatar/animations/talk.fbx b/interface/resources/avatar/animations/talk.fbx index c29bf1e9bf..6cc34049be 100644 Binary files a/interface/resources/avatar/animations/talk.fbx and b/interface/resources/avatar/animations/talk.fbx differ diff --git a/interface/resources/avatar/animations/talk02.fbx b/interface/resources/avatar/animations/talk02.fbx new file mode 100644 index 0000000000..a502ff261b Binary files /dev/null and b/interface/resources/avatar/animations/talk02.fbx differ diff --git a/interface/resources/avatar/animations/talk03.fbx b/interface/resources/avatar/animations/talk03.fbx new file mode 100644 index 0000000000..da95717540 Binary files /dev/null and b/interface/resources/avatar/animations/talk03.fbx differ diff --git a/interface/resources/avatar/animations/talk04.fbx b/interface/resources/avatar/animations/talk04.fbx index be2ba0a11f..9e5505b969 100644 Binary files a/interface/resources/avatar/animations/talk04.fbx and b/interface/resources/avatar/animations/talk04.fbx differ diff --git a/interface/resources/avatar/animations/talk_armsdown.fbx b/interface/resources/avatar/animations/talk_armsdown.fbx new file mode 100644 index 0000000000..e069811f7c Binary files /dev/null and b/interface/resources/avatar/animations/talk_armsdown.fbx differ diff --git a/interface/resources/avatar/animations/talk_lefthand.fbx b/interface/resources/avatar/animations/talk_lefthand.fbx new file mode 100644 index 0000000000..d7fd1d5e07 Binary files /dev/null and b/interface/resources/avatar/animations/talk_lefthand.fbx differ diff --git a/interface/resources/avatar/animations/talk_righthand.fbx b/interface/resources/avatar/animations/talk_righthand.fbx index df8849b4b4..332afcc1e7 100644 Binary files a/interface/resources/avatar/animations/talk_righthand.fbx and b/interface/resources/avatar/animations/talk_righthand.fbx differ diff --git a/interface/resources/avatar/animations/teleport.fbx b/interface/resources/avatar/animations/teleport.fbx deleted file mode 100644 index 99c950ced6..0000000000 Binary files a/interface/resources/avatar/animations/teleport.fbx and /dev/null differ diff --git a/interface/resources/avatar/animations/turn_left.fbx b/interface/resources/avatar/animations/turn_left.fbx index 3d32d832e6..b7cadf7a66 100644 Binary files a/interface/resources/avatar/animations/turn_left.fbx and b/interface/resources/avatar/animations/turn_left.fbx differ diff --git a/interface/resources/avatar/animations/turn_right.fbx b/interface/resources/avatar/animations/turn_right.fbx new file mode 100644 index 0000000000..4ee3d52daf Binary files /dev/null and b/interface/resources/avatar/animations/turn_right.fbx differ diff --git a/interface/resources/avatar/animations/walk_bwd.fbx b/interface/resources/avatar/animations/walk_bwd.fbx index 158ba52840..9daa769885 100644 Binary files a/interface/resources/avatar/animations/walk_bwd.fbx and b/interface/resources/avatar/animations/walk_bwd.fbx differ diff --git a/interface/resources/avatar/animations/walk_bwd_fast.fbx b/interface/resources/avatar/animations/walk_bwd_fast.fbx index f9a9ba0e26..af22d0d0b0 100644 Binary files a/interface/resources/avatar/animations/walk_bwd_fast.fbx and b/interface/resources/avatar/animations/walk_bwd_fast.fbx differ diff --git a/interface/resources/avatar/animations/walk_fwd.fbx b/interface/resources/avatar/animations/walk_fwd.fbx index 8ad461f62e..f86a8744c9 100644 Binary files a/interface/resources/avatar/animations/walk_fwd.fbx and b/interface/resources/avatar/animations/walk_fwd.fbx differ diff --git a/interface/resources/avatar/animations/walk_fwd_fast.fbx b/interface/resources/avatar/animations/walk_fwd_fast.fbx index db440fc9c4..8d2becf4b8 100644 Binary files a/interface/resources/avatar/animations/walk_fwd_fast.fbx and b/interface/resources/avatar/animations/walk_fwd_fast.fbx differ diff --git a/interface/resources/avatar/animations/walk_fwd_fast02.fbx b/interface/resources/avatar/animations/walk_fwd_fast02.fbx deleted file mode 100644 index 470b1d57f3..0000000000 Binary files a/interface/resources/avatar/animations/walk_fwd_fast02.fbx and /dev/null differ diff --git a/interface/resources/avatar/animations/walk_fwd_fast_armout.fbx b/interface/resources/avatar/animations/walk_fwd_fast_armout.fbx deleted file mode 100644 index 6aa07d0a45..0000000000 Binary files a/interface/resources/avatar/animations/walk_fwd_fast_armout.fbx and /dev/null differ diff --git a/interface/resources/avatar/animations/walk_left.fbx b/interface/resources/avatar/animations/walk_left.fbx index bfe10aa18f..f35d4f6a77 100644 Binary files a/interface/resources/avatar/animations/walk_left.fbx and b/interface/resources/avatar/animations/walk_left.fbx differ diff --git a/interface/resources/avatar/animations/walk_left_fast.fbx b/interface/resources/avatar/animations/walk_left_fast.fbx index ced6c08bac..8414ee6805 100644 Binary files a/interface/resources/avatar/animations/walk_left_fast.fbx and b/interface/resources/avatar/animations/walk_left_fast.fbx differ diff --git a/interface/resources/avatar/animations/walk_right.fbx b/interface/resources/avatar/animations/walk_right.fbx new file mode 100644 index 0000000000..5fe005f96c Binary files /dev/null and b/interface/resources/avatar/animations/walk_right.fbx differ diff --git a/interface/resources/avatar/animations/walk_right_fast.fbx b/interface/resources/avatar/animations/walk_right_fast.fbx new file mode 100644 index 0000000000..37b7bbbb62 Binary files /dev/null and b/interface/resources/avatar/animations/walk_right_fast.fbx differ diff --git a/interface/resources/avatar/animations/walk_short_bwd.fbx b/interface/resources/avatar/animations/walk_short_bwd.fbx deleted file mode 100644 index d7e4bedf53..0000000000 Binary files a/interface/resources/avatar/animations/walk_short_bwd.fbx and /dev/null differ diff --git a/interface/resources/avatar/animations/walk_short_fwd.fbx b/interface/resources/avatar/animations/walk_short_fwd.fbx index 51f0794ac1..b52371869b 100644 Binary files a/interface/resources/avatar/animations/walk_short_fwd.fbx and b/interface/resources/avatar/animations/walk_short_fwd.fbx differ diff --git a/interface/resources/avatar/avatar-animation.json b/interface/resources/avatar/avatar-animation.json index fd206ce475..b1277a26f5 100644 --- a/interface/resources/avatar/avatar-animation.json +++ b/interface/resources/avatar/avatar-animation.json @@ -733,7 +733,7 @@ }, { "id": "turnRight", - "interpTarget": 6, + "interpTarget": 8, "interpDuration": 8, "transitions": [ { "var": "isNotTurning", "state": "idle" }, @@ -753,7 +753,7 @@ }, { "id": "turnLeft", - "interpTarget": 6, + "interpTarget": 8, "interpDuration": 8, "transitions": [ { "var": "isNotTurning", "state": "idle" }, @@ -773,7 +773,7 @@ }, { "id": "strafeRightHmd", - "interpTarget": 5, + "interpTarget": 8, "interpDuration": 8, "interpType": "snapshotPrev", "transitions": [ @@ -794,7 +794,7 @@ }, { "id": "strafeLeftHmd", - "interpTarget": 5, + "interpTarget": 8, "interpDuration": 8, "interpType": "snapshotPrev", "transitions": [ @@ -905,40 +905,72 @@ "id": "idle", "type": "overlay", "data": { - "alpha": 1.0, + "alpha": 1.0, "alphaVar": "idleOverlayAlpha", "boneSet": "upperBody" }, "children": [ - { - "id": "idleTalk", + { + "id": "idleTalk", "type": "randomSwitchStateMachine", "data": { - "currentState": "idleTalk1", - "triggerRandomSwitch": "idleTalkSwitch", - "randomSwitchTimeMin": 5.0, - "randomSwitchTimeMax": 10.0, + "currentState": "talk", + "triggerRandomSwitch": "idleTalkSwitch", + "randomSwitchTimeMin": 7.0, + "randomSwitchTimeMax": 12.0, "states": [ { - "id": "idleTalk1", - "interpTarget": 6, - "interpDuration": 15, + "id": "talk", + "interpTarget": 20, + "interpDuration": 20, "priority": 0.33, "resume": true, "transitions": [] }, { - "id": "idleTalk2", - "interpTarget": 6, - "interpDuration": 15, + "id": "talk02", + "interpTarget": 20, + "interpDuration": 20, "priority": 0.33, "resume": true, "transitions": [] }, { - "id": "idleTalk3", - "interpTarget": 6, - "interpDuration": 15, + "id": "talk03", + "interpTarget": 20, + "interpDuration": 20, + "priority": 0.33, + "resume": true, + "transitions": [] + }, + { + "id": "talk04", + "interpTarget": 20, + "interpDuration": 20, + "priority": 0.33, + "resume": true, + "transitions": [] + }, + { + "id": "talk_armsdown", + "interpTarget": 20, + "interpDuration": 20, + "priority": 0.33, + "resume": true, + "transitions": [] + }, + { + "id": "talk_lefthand", + "interpTarget": 20, + "interpDuration": 20, + "priority": 0.33, + "resume": true, + "transitions": [] + }, + { + "id": "talk_righthand", + "interpTarget": 20, + "interpDuration": 20, "priority": 0.33, "resume": true, "transitions": [] @@ -947,57 +979,105 @@ }, "children": [ { - "id": "idleTalk1", + "id": "talk", "type": "clip", "data": { "url": "qrc:///avatar/animations/talk.fbx", "startFrame": 1.0, - "endFrame": 800.0, + "endFrame": 500.0, "timeScale": 1.0, "loopFlag": true }, "children": [] }, { - "id": "idleTalk2", + "id": "talk02", "type": "clip", "data": { - "url": "qrc:///avatar/animations/talk_righthand.fbx", + "url": "qrc:///avatar/animations/talk02.fbx", "startFrame": 1.0, - "endFrame": 501.0, + "endFrame": 325.0, "timeScale": 1.0, "loopFlag": true }, "children": [] }, { - "id": "idleTalk3", + "id": "talk03", + "type": "clip", + "data": { + "url": "qrc:///avatar/animations/talk03.fbx", + "startFrame": 1.0, + "endFrame": 300.0, + "timeScale": 1.0, + "loopFlag": true + }, + "children": [] + }, + { + "id": "talk04", "type": "clip", "data": { "url": "qrc:///avatar/animations/talk04.fbx", "startFrame": 1.0, - "endFrame": 499.0, + "endFrame": 500.0, + "timeScale": 1.0, + "loopFlag": true + }, + "children": [] + }, + { + "id": "talk_armsdown", + "type": "clip", + "data": { + "url": "qrc:///avatar/animations/talk_armsdown.fbx", + "startFrame": 1.0, + "endFrame": 215.0, + "timeScale": 1.0, + "loopFlag": true + }, + "children": [] + }, + { + "id": "talk_lefthand", + "type": "clip", + "data": { + "url": "qrc:///avatar/animations/talk_lefthand.fbx", + "startFrame": 1.0, + "endFrame": 500.0, + "timeScale": 1.0, + "loopFlag": true + }, + "children": [] + }, + { + "id": "talk_righthand", + "type": "clip", + "data": { + "url": "qrc:///avatar/animations/talk_righthand.fbx", + "startFrame": 1.0, + "endFrame": 502.0, "timeScale": 1.0, "loopFlag": true }, "children": [] } ] - }, + }, { "id": "idleStand", "type": "randomSwitchStateMachine", "data": { "currentState": "masterIdle", - "triggerTimeMin": 10.0, - "triggerTimeMax": 60.0, - "transitionVar": "timeToFidget", + "triggerTimeMin": 10.0, + "triggerTimeMax": 50.0, + "transitionVar": "timeToFidget", "states": [ { "id": "masterIdle", "interpTarget": 21, "interpDuration": 20, - "priority": 1.0, + "priority": 1.0, "resume": false, "transitions": [ { "var": "timeToFidget", "randomSwitchState": "fidget" } @@ -1007,17 +1087,17 @@ "id": "fidget", "interpTarget": 21, "interpDuration": 20, - "priority": -1.0, + "priority": -1.0, "resume": false, "transitions": [ - { "var": "movement1OnDone", "randomSwitchState": "masterIdle" }, - { "var": "movement2OnDone", "randomSwitchState": "masterIdle" }, - { "var": "movement3OnDone", "randomSwitchState": "masterIdle" }, - { "var": "movement4OnDone", "randomSwitchState": "masterIdle" }, - { "var": "movement5OnDone", "randomSwitchState": "masterIdle" }, - { "var": "movement6OnDone", "randomSwitchState": "masterIdle" }, - { "var": "movement7OnDone", "randomSwitchState": "masterIdle" }, - { "var": "movement8OnDone", "randomSwitchState": "masterIdle" }, + { "var": "idle_once_slownodOnDone", "randomSwitchState": "masterIdle" }, + { "var": "idle_once_headtiltOnDone", "randomSwitchState": "masterIdle" }, + { "var": "idle_once_shiftheelpivotOnDone", "randomSwitchState": "masterIdle" }, + { "var": "idleWS_allOnDone", "randomSwitchState": "masterIdle" }, + { "var": "idle_once_lookaroundOnDone", "randomSwitchState": "masterIdle" }, + { "var": "idle_once_neckstretchOnDone", "randomSwitchState": "masterIdle" }, + { "var": "idle_once_lookleftrightOnDone", "randomSwitchState": "masterIdle" }, + { "var": "idle_once_fidgetOnDone", "randomSwitchState": "masterIdle" }, { "var": "alt1ToMasterIdleOnDone", "randomSwitchState": "masterIdle" }, { "var": "alt2ToMasterIdleOnDone", "randomSwitchState": "masterIdle" } ] @@ -1032,13 +1112,13 @@ "currentState": "masterIdle1", "triggerRandomSwitch": "masterIdleSwitch", "randomSwitchTimeMin": 10.0, - "randomSwitchTimeMax": 60.0, + "randomSwitchTimeMax": 30.0, "states": [ { "id": "masterIdle1", "interpTarget": 21, "interpDuration": 20, - "priority": 0.33, + "priority": 0.25, "resume": true, "transitions": [] }, @@ -1046,7 +1126,7 @@ "id": "masterIdle2", "interpTarget": 21, "interpDuration": 20, - "priority": 0.33, + "priority": 0.25, "resume": true, "transitions": [] }, @@ -1054,7 +1134,15 @@ "id": "masterIdle3", "interpTarget": 21, "interpDuration": 20, - "priority": 0.33, + "priority": 0.25, + "resume": true, + "transitions": [] + }, + { + "id": "masterIdle4", + "interpTarget": 21, + "interpDuration": 20, + "priority": 0.25, "resume": true, "transitions": [] } @@ -1077,10 +1165,10 @@ "id": "masterIdle2", "type": "clip", "data": { - "url": "qrc:///avatar/animations/idleWS_all.fbx", + "url": "qrc:///avatar/animations/idle02.fbx", "startFrame": 1.0, - "endFrame": 1620.0, - "timeScale": 1.0, + "endFrame": 400.0, + "timeScale": 0.75, "loopFlag": true }, "children": [] @@ -1089,9 +1177,21 @@ "id": "masterIdle3", "type": "clip", "data": { - "url": "qrc:///avatar/animations/idle_lookaround01.fbx", + "url": "qrc:///avatar/animations/idle03.fbx", "startFrame": 1.0, - "endFrame": 901.0, + "endFrame": 800.0, + "timeScale": 1.0, + "loopFlag": true + }, + "children": [] + }, + { + "id": "masterIdle4", + "type": "clip", + "data": { + "url": "qrc:///avatar/animations/idle04.fbx", + "startFrame": 1.0, + "endFrame": 902.0, "timeScale": 1.0, "loopFlag": true }, @@ -1109,7 +1209,7 @@ "id": "movement", "interpTarget": 17, "interpDuration": 15, - "priority": 0.8, + "priority": 0.6, "resume": false, "transitions": [] }, @@ -1117,7 +1217,7 @@ "id": "alternateIdle", "interpTarget": 17, "interpDuration": 15, - "priority": 0.2, + "priority": 0.4, "resume": false, "transitions": [] } @@ -1128,10 +1228,10 @@ "id": "movement", "type": "randomSwitchStateMachine", "data": { - "currentState": "movement1", + "currentState": "idle_once_slownod", "states": [ { - "id": "movement1", + "id": "idle_once_slownod", "interpTarget": 21, "interpDuration": 20, "priority": 0.2, @@ -1139,7 +1239,7 @@ "transitions": [] }, { - "id": "movement2", + "id": "idle_once_headtilt", "interpTarget": 21, "interpDuration": 20, "priority": 0.2, @@ -1147,7 +1247,7 @@ "transitions": [] }, { - "id": "movement3", + "id": "idle_once_shiftheelpivot", "interpTarget": 21, "interpDuration": 20, "priority": 0.2, @@ -1155,7 +1255,7 @@ "transitions": [] }, { - "id": "movement4", + "id": "idleWS_all", "interpTarget": 21, "interpDuration": 20, "priority": 0.2, @@ -1163,7 +1263,7 @@ "transitions": [] }, { - "id": "movement5", + "id": "idle_once_lookaround", "interpTarget": 21, "interpDuration": 20, "priority": 0.2, @@ -1171,7 +1271,7 @@ "transitions": [] }, { - "id": "movement6", + "id": "idle_once_neckstretch", "interpTarget": 21, "interpDuration": 20, "priority": 0.2, @@ -1179,7 +1279,7 @@ "transitions": [] }, { - "id": "movement7", + "id": "idle_once_lookleftright", "interpTarget": 21, "interpDuration": 20, "priority": 0.2, @@ -1187,7 +1287,7 @@ "transitions": [] }, { - "id": "movement8", + "id": "idle_once_fidget", "interpTarget": 21, "interpDuration": 20, "priority": 0.2, @@ -1198,11 +1298,11 @@ }, "children": [ { - "id": "movement1", + "id": "idle_once_slownod", "type": "clip", "data": { "url": "qrc:///avatar/animations/idle_once_slownod.fbx", - "startFrame": 1, + "startFrame": 1.0, "endFrame": 91.0, "timeScale": 1.0, "loopFlag": false @@ -1210,84 +1310,84 @@ "children": [] }, { - "id": "movement2", + "id": "idle_once_headtilt", "type": "clip", "data": { "url": "qrc:///avatar/animations/idle_once_headtilt.fbx", - "startFrame": 1, - "endFrame": 154, + "startFrame": 1.0, + "endFrame": 154.0, "timeScale": 1.0, "loopFlag": false }, "children": [] }, { - "id": "movement3", + "id": "idle_once_shiftheelpivot", "type": "clip", "data": { - "url": "qrc:///avatar/animations/idle_once_headtilt.fbx", - "startFrame": 1, - "endFrame": 154, + "url": "qrc:///avatar/animations/idle_once_shiftheelpivot.fbx", + "startFrame": 1.0, + "endFrame": 491.0, "timeScale": 1.0, "loopFlag": false }, "children": [] }, { - "id": "movement4", + "id": "idleWS_all", "type": "clip", "data": { "url": "qrc:///avatar/animations/idleWS_all.fbx", - "startFrame": 1, - "endFrame": 1620, - "timeScale": 1.0, + "startFrame": 1.0, + "endFrame": 1620.0, + "timeScale": 0.7, "loopFlag": false }, "children": [] }, { - "id": "movement5", + "id": "idle_once_lookaround", "type": "clip", "data": { "url": "qrc:///avatar/animations/idle_once_lookaround.fbx", - "startFrame": 1, - "endFrame": 324, + "startFrame": 1.0, + "endFrame": 324.0, "timeScale": 1.0, "loopFlag": false }, "children": [] }, { - "id": "movement6", + "id": "idle_once_neckstretch", "type": "clip", "data": { "url": "qrc:///avatar/animations/idle_once_neckstretch.fbx", - "startFrame": 1, - "endFrame": 169, + "startFrame": 1.0, + "endFrame": 169.0, "timeScale": 1.0, "loopFlag": false }, "children": [] }, { - "id": "movement7", + "id": "idle_once_lookleftright", "type": "clip", "data": { - "url": "qrc:///avatar/animations/idleWS_all.fbx", - "startFrame": 1, - "endFrame": 1620, - "timeScale": 1.0, + "url": "qrc:///avatar/animations/idle_once_lookleftright.fbx", + "startFrame": 1.0, + "endFrame": 375.0, + "timeScale": 0.7, "loopFlag": false }, "children": [] }, { - "id": "movement8", + "id": "idle_once_fidget", "type": "clip", "data": { - "url": "qrc:///avatar/animations/idle_once_lookaround.fbx", - "startFrame": 1, - "endFrame": 324, + "url": "qrc:///avatar/animations/idle_once_fidget.fbx", + "startFrame": 1.0, + "endFrame": 429.0, "timeScale": 1.0, "loopFlag": false }, @@ -1381,7 +1481,7 @@ "data": { "url": "qrc:///avatar/animations/idle_LFF_all.fbx", "startFrame": 1, - "endFrame": 55, + "endFrame": 80, "timeScale": 1.0, "loopFlag": false }, @@ -1392,8 +1492,8 @@ "type": "clip", "data": { "url": "qrc:///avatar/animations/idle_RFF_all.fbx", - "startFrame": 1, - "endFrame": 56, + "startFrame": 1.0, + "endFrame": 80.0, "timeScale": 1.0, "loopFlag": false }, @@ -1404,7 +1504,7 @@ "type": "clip", "data": { "url": "qrc:///avatar/animations/idle_LFF_all.fbx", - "startFrame": 55, + "startFrame": 80, "endFrame": 389, "timeScale": 1.0, "loopFlag": true @@ -1416,8 +1516,8 @@ "type": "clip", "data": { "url": "qrc:///avatar/animations/idle_RFF_all.fbx", - "startFrame": 56, - "endFrame": 390, + "startFrame": 80.0, + "endFrame": 390.0, "timeScale": 1.0, "loopFlag": true }, @@ -1440,8 +1540,8 @@ "type": "clip", "data": { "url": "qrc:///avatar/animations/idle_RFF_all.fbx", - "startFrame": 390, - "endFrame": 453, + "startFrame": 390.0, + "endFrame": 453.0, "timeScale": 1.0, "loopFlag": false }, @@ -1463,7 +1563,7 @@ "data": { "alpha": 0.0, "desiredSpeed": 1.4, - "characteristicSpeeds": [0.5, 1.8, 2.3, 3.0, 5.0], + "characteristicSpeeds": [0.5, 1.8, 2.5, 3.55, 5.675], "alphaVar": "moveForwardAlpha", "desiredSpeedVar": "moveForwardSpeed" }, @@ -1473,8 +1573,8 @@ "type": "clip", "data": { "url": "qrc:///avatar/animations/walk_short_fwd.fbx", - "startFrame": 0.0, - "endFrame": 39.0, + "startFrame": 1.0, + "endFrame": 40.0, "timeScale": 1.0, "loopFlag": true }, @@ -1485,7 +1585,7 @@ "type": "clip", "data": { "url": "qrc:///avatar/animations/walk_fwd.fbx", - "startFrame": 0.0, + "startFrame": 1.0, "endFrame": 30.0, "timeScale": 1.0, "loopFlag": true @@ -1497,8 +1597,8 @@ "type": "clip", "data": { "url": "qrc:///avatar/animations/walk_fwd_fast.fbx", - "startFrame": 0.0, - "endFrame": 25.0, + "startFrame": 1.0, + "endFrame": 26.0, "timeScale": 1.0, "loopFlag": true }, @@ -1510,7 +1610,7 @@ "data": { "url": "qrc:///avatar/animations/jog_fwd.fbx", "startFrame": 1.0, - "endFrame": 22.0, + "endFrame": 18.0, "timeScale": 1.0, "loopFlag": true }, @@ -1520,9 +1620,9 @@ "id": "walkFwdRun_c", "type": "clip", "data": { - "url": "qrc:///avatar/animations/run_fwd.fbx", + "url": "qrc:///avatar/animations/run_fast_fwd.fbx", "startFrame": 1.0, - "endFrame": 23.0, + "endFrame": 19.0, "timeScale": 1.0, "loopFlag": true }, @@ -1546,7 +1646,7 @@ "id": "idleSettle", "type": "clip", "data": { - "url": "qrc:///avatar/animations/settle_to_idle.fbx", + "url": "qrc:///avatar/animations/settle_to_idle_small.fbx", "startFrame": 1.0, "endFrame": 59.0, "timeScale": 1.0, @@ -1560,7 +1660,7 @@ "data": { "alpha": 0.0, "desiredSpeed": 1.4, - "characteristicSpeeds": [0.6, 1.6, 2.3, 3.1], + "characteristicSpeeds": [0.6, 1.6, 2.8, 4.5], "alphaVar": "moveBackwardAlpha", "desiredSpeedVar": "moveBackwardSpeed" }, @@ -1569,9 +1669,9 @@ "id": "walkBwdShort_c", "type": "clip", "data": { - "url": "qrc:///avatar/animations/walk_short_bwd.fbx", - "startFrame": 0.0, - "endFrame": 38.0, + "url": "qrc:///avatar/animations/walk_bwd.fbx", + "startFrame": 1.0, + "endFrame": 37.0, "timeScale": 1.0, "loopFlag": true }, @@ -1582,8 +1682,8 @@ "type": "clip", "data": { "url": "qrc:///avatar/animations/walk_bwd_fast.fbx", - "startFrame": 0.0, - "endFrame": 27.0, + "startFrame": 1.0, + "endFrame": 28.0, "timeScale": 1.0, "loopFlag": true }, @@ -1594,8 +1694,8 @@ "type": "clip", "data": { "url": "qrc:///avatar/animations/jog_bwd.fbx", - "startFrame": 0.0, - "endFrame": 24.0, + "startFrame": 1.0, + "endFrame": 20.0, "timeScale": 1.0, "loopFlag": true }, @@ -1606,8 +1706,8 @@ "type": "clip", "data": { "url": "qrc:///avatar/animations/run_bwd.fbx", - "startFrame": 0.0, - "endFrame": 16.0, + "startFrame": 1.0, + "endFrame": 14.0, "timeScale": 1.0, "loopFlag": true }, @@ -1620,8 +1720,8 @@ "type": "clip", "data": { "url": "qrc:///avatar/animations/turn_left.fbx", - "startFrame": 0.0, - "endFrame": 32.0, + "startFrame": 1.0, + "endFrame": 33.0, "timeScale": 1.0, "loopFlag": true }, @@ -1631,12 +1731,12 @@ "id": "turnRight", "type": "clip", "data": { - "url": "qrc:///avatar/animations/turn_left.fbx", - "startFrame": 0.0, - "endFrame": 32.0, + "url": "qrc:///avatar/animations/turn_right.fbx", + "startFrame": 1.0, + "endFrame": 31.0, "timeScale": 1.0, "loopFlag": true, - "mirrorFlag": true + "mirrorFlag": false }, "children": [] }, @@ -1646,7 +1746,7 @@ "data": { "alpha": 0.0, "desiredSpeed": 1.4, - "characteristicSpeeds": [0.1, 0.5, 1.0, 2.6, 3.0], + "characteristicSpeeds": [0.1, 0.5, 1.0, 2.55, 3.35, 5.25], "alphaVar": "moveLateralAlpha", "desiredSpeedVar": "moveLateralSpeed" }, @@ -1656,8 +1756,8 @@ "type": "clip", "data": { "url": "qrc:///avatar/animations/side_step_short_left.fbx", - "startFrame": 0.0, - "endFrame": 29.0, + "startFrame": 1.0, + "endFrame": 30.0, "timeScale": 1.0, "loopFlag": true }, @@ -1668,7 +1768,7 @@ "type": "clip", "data": { "url": "qrc:///avatar/animations/side_step_left.fbx", - "startFrame": 0.0, + "startFrame": 1.0, "endFrame": 20.0, "timeScale": 1.0, "loopFlag": true @@ -1680,7 +1780,7 @@ "type": "clip", "data": { "url": "qrc:///avatar/animations/walk_left.fbx", - "startFrame": 0.0, + "startFrame": 1.0, "endFrame": 35.0, "timeScale": 1.0, "loopFlag": true @@ -1692,7 +1792,7 @@ "type": "clip", "data": { "url": "qrc:///avatar/animations/walk_left_fast.fbx", - "startFrame": 0.0, + "startFrame": 1.0, "endFrame": 21.0, "timeScale": 1.0, "loopFlag": true @@ -1704,8 +1804,20 @@ "type": "clip", "data": { "url": "qrc:///avatar/animations/jog_left.fbx", - "startFrame": 0.0, - "endFrame": 24.0, + "startFrame": 1.0, + "endFrame": 20.0, + "timeScale": 1.0, + "loopFlag": true + }, + "children": [] + }, + { + "id": "strafeLeftRun_c", + "type": "clip", + "data": { + "url": "qrc:///avatar/animations/run_fast_left.fbx", + "startFrame": 1.0, + "endFrame": 19.0, "timeScale": 1.0, "loopFlag": true }, @@ -1719,7 +1831,7 @@ "data": { "alpha": 0.0, "desiredSpeed": 1.4, - "characteristicSpeeds": [0.1, 0.5, 1.0, 2.6, 3.0], + "characteristicSpeeds": [0.1, 0.5, 1.0, 2.55, 3.4, 5.25], "alphaVar": "moveLateralAlpha", "desiredSpeedVar": "moveLateralSpeed" }, @@ -1728,8 +1840,8 @@ "type": "clip", "data": { "url": "qrc:///avatar/animations/side_step_short_left.fbx", - "startFrame": 0.0, - "endFrame": 29.0, + "startFrame": 1.0, + "endFrame": 30.0, "timeScale": 1.0, "loopFlag": true, "mirrorFlag": true @@ -1741,7 +1853,7 @@ "type": "clip", "data": { "url": "qrc:///avatar/animations/side_step_left.fbx", - "startFrame": 0.0, + "startFrame": 1.0, "endFrame": 20.0, "timeScale": 1.0, "loopFlag": true, @@ -1753,12 +1865,12 @@ "id": "strafeRightWalk_c", "type": "clip", "data": { - "url": "qrc:///avatar/animations/walk_left.fbx", - "startFrame": 0.0, + "url": "qrc:///avatar/animations/walk_right.fbx", + "startFrame": 1.0, "endFrame": 35.0, "timeScale": 1.0, "loopFlag": true, - "mirrorFlag": true + "mirrorFlag": false }, "children": [] }, @@ -1766,12 +1878,12 @@ "id": "strafeRightFast_c", "type": "clip", "data": { - "url": "qrc:///avatar/animations/walk_left_fast.fbx", - "startFrame": 0.0, + "url": "qrc:///avatar/animations/walk_right_fast.fbx", + "startFrame": 1.0, "endFrame": 21.0, "timeScale": 1.0, "loopFlag": true, - "mirrorFlag": true + "mirrorFlag": false }, "children": [] }, @@ -1779,12 +1891,25 @@ "id": "strafeRightJog_c", "type": "clip", "data": { - "url": "qrc:///avatar/animations/jog_left.fbx", - "startFrame": 0.0, - "endFrame": 24.0, + "url": "qrc:///avatar/animations/jog_right.fbx", + "startFrame": 1.0, + "endFrame": 20.0, "timeScale": 1.0, "loopFlag": true, - "mirrorFlag": true + "mirrorFlag": false + }, + "children": [] + }, + { + "id": "strafeRightRun_c", + "type": "clip", + "data": { + "url": "qrc:///avatar/animations/run_fast_right.fbx", + "startFrame": 1.0, + "endFrame": 19.0, + "timeScale": 1.0, + "loopFlag": true, + "mirrorFlag": false }, "children": [] } @@ -1806,8 +1931,8 @@ "type": "clip", "data": { "url": "qrc:///avatar/animations/side_step_short_left.fbx", - "startFrame": 0.0, - "endFrame": 29.0, + "startFrame": 1.0, + "endFrame": 30.0, "timeScale": 1.0, "loopFlag": true }, @@ -1818,7 +1943,7 @@ "type": "clip", "data": { "url": "qrc:///avatar/animations/side_step_left.fbx", - "startFrame": 0.0, + "startFrame": 1.0, "endFrame": 20.0, "timeScale": 1.0, "loopFlag": true @@ -1830,7 +1955,7 @@ "type": "clip", "data": { "url": "qrc:///avatar/animations/side_step_left_fast.fbx", - "startFrame": 0.0, + "startFrame": 1.0, "endFrame": 16.0, "timeScale": 1.0, "loopFlag": true @@ -1855,8 +1980,8 @@ "type": "clip", "data": { "url": "qrc:///avatar/animations/side_step_short_left.fbx", - "startFrame": 0.0, - "endFrame": 29.0, + "startFrame": 1.0, + "endFrame": 30.0, "timeScale": 1.0, "loopFlag": true, "mirrorFlag": true @@ -1868,7 +1993,7 @@ "type": "clip", "data": { "url": "qrc:///avatar/animations/side_step_left.fbx", - "startFrame": 0.0, + "startFrame": 1.0, "endFrame": 20.0, "timeScale": 1.0, "loopFlag": true, @@ -1881,7 +2006,7 @@ "type": "clip", "data": { "url": "qrc:///avatar/animations/side_step_left_fast.fbx", - "startFrame": 0.0, + "startFrame": 1.0, "endFrame": 16.0, "timeScale": 1.0, "loopFlag": true, @@ -1897,7 +2022,7 @@ "data": { "url": "qrc:///avatar/animations/fly.fbx", "startFrame": 1.0, - "endFrame": 80.0, + "endFrame": 79.0, "timeScale": 1.0, "loopFlag": true }, @@ -1907,8 +2032,8 @@ "id": "takeoffStand", "type": "clip", "data": { - "url": "qrc:///avatar/animations/jump_standing_launch.fbx", - "startFrame": 2.0, + "url": "qrc:///avatar/animations/jump_standing_launch_all.fbx", + "startFrame": 1.0, "endFrame": 16.0, "timeScale": 1.0, "loopFlag": false @@ -1919,7 +2044,7 @@ "id": "TAKEOFFRUN", "type": "clip", "data": { - "url": "qrc:///avatar/animations/jump_running_launch_land.fbx", + "url": "qrc:///avatar/animations/jump_running_launch_land_all.fbx", "startFrame": 4.0, "endFrame": 15.0, "timeScale": 1.0, @@ -1939,9 +2064,9 @@ "id": "inAirStandPreApex", "type": "clip", "data": { - "url": "qrc:///avatar/animations/jump_standing_apex.fbx", - "startFrame": 0.0, - "endFrame": 0.0, + "url": "qrc:///avatar/animations/jump_standing_apex_all.fbx", + "startFrame": 1.0, + "endFrame": 1.0, "timeScale": 1.0, "loopFlag": false }, @@ -1951,9 +2076,9 @@ "id": "inAirStandApex", "type": "clip", "data": { - "url": "qrc:///avatar/animations/jump_standing_apex.fbx", - "startFrame": 1.0, - "endFrame": 1.0, + "url": "qrc:///avatar/animations/jump_standing_apex_all.fbx", + "startFrame": 2.0, + "endFrame": 2.0, "timeScale": 1.0, "loopFlag": false }, @@ -1963,9 +2088,9 @@ "id": "inAirStandPostApex", "type": "clip", "data": { - "url": "qrc:///avatar/animations/jump_standing_apex.fbx", - "startFrame": 2.0, - "endFrame": 2.0, + "url": "qrc:///avatar/animations/jump_standing_apex_all.fbx", + "startFrame": 3.0, + "endFrame": 3.0, "timeScale": 1.0, "loopFlag": false }, @@ -1985,7 +2110,7 @@ "id": "inAirRunPreApex", "type": "clip", "data": { - "url": "qrc:///avatar/animations/jump_running_launch_land.fbx", + "url": "qrc:///avatar/animations/jump_running_launch_land_all.fbx", "startFrame": 16.0, "endFrame": 16.0, "timeScale": 1.0, @@ -1997,7 +2122,7 @@ "id": "inAirRunApex", "type": "clip", "data": { - "url": "qrc:///avatar/animations/jump_running_launch_land.fbx", + "url": "qrc:///avatar/animations/jump_running_launch_land_all.fbx", "startFrame": 22.0, "endFrame": 22.0, "timeScale": 1.0, @@ -2009,7 +2134,7 @@ "id": "inAirRunPostApex", "type": "clip", "data": { - "url": "qrc:///avatar/animations/jump_running_launch_land.fbx", + "url": "qrc:///avatar/animations/jump_running_launch_land_all.fbx", "startFrame": 33.0, "endFrame": 33.0, "timeScale": 1.0, @@ -2023,7 +2148,7 @@ "id": "landStandImpact", "type": "clip", "data": { - "url": "qrc:///avatar/animations/jump_standing_land_settle.fbx", + "url": "qrc:///avatar/animations/jump_standing_land_settle_all.fbx", "startFrame": 1.0, "endFrame": 6.0, "timeScale": 1.0, @@ -2035,7 +2160,7 @@ "id": "landStand", "type": "clip", "data": { - "url": "qrc:///avatar/animations/jump_standing_land_settle.fbx", + "url": "qrc:///avatar/animations/jump_standing_land_settle_all.fbx", "startFrame": 6.0, "endFrame": 68.0, "timeScale": 1.0, @@ -2047,7 +2172,7 @@ "id": "LANDRUN", "type": "clip", "data": { - "url": "qrc:///avatar/animations/jump_running_launch_land.fbx", + "url": "qrc:///avatar/animations/jump_running_launch_land_all.fbx", "startFrame": 29.0, "endFrame": 40.0, "timeScale": 1.0, @@ -2078,8 +2203,8 @@ "type": "clip", "data": { "url": "qrc:///avatar/animations/idle.fbx", - "startFrame": 0.0, - "endFrame": 90.0, + "startFrame": 1.0, + "endFrame": 300.0, "timeScale": 1.0, "loopFlag": true }, @@ -2090,8 +2215,8 @@ "type": "clip", "data": { "url": "qrc:///avatar/animations/idle.fbx", - "startFrame": 0.0, - "endFrame": 90.0, + "startFrame": 1.0, + "endFrame": 300.0, "timeScale": 1.0, "loopFlag": true }, @@ -2099,4 +2224,4 @@ } ] } -} +} \ No newline at end of file diff --git a/interface/resources/qml/+webengine/BrowserWebView.qml b/interface/resources/qml/+webengine/BrowserWebView.qml index 5c5cf2cfb9..137531f517 100644 --- a/interface/resources/qml/+webengine/BrowserWebView.qml +++ b/interface/resources/qml/+webengine/BrowserWebView.qml @@ -29,16 +29,6 @@ WebView { userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard ] - onFeaturePermissionRequested: { - if (feature == 2) { // QWebEnginePage::MediaAudioCapture - grantFeaturePermission(securityOrigin, feature, true); - } else { - permissionsBar.securityOrigin = securityOrigin; - permissionsBar.feature = feature; - parentRoot.showPermissionsBar(); - } - } - onLoadingChanged: { if (loadRequest.status === WebEngineView.LoadSucceededStatus) { addressBar.text = loadRequest.url diff --git a/interface/resources/qml/+webengine/TabletBrowser.qml b/interface/resources/qml/+webengine/TabletBrowser.qml index 720a904231..3bb2c17ba6 100644 --- a/interface/resources/qml/+webengine/TabletBrowser.qml +++ b/interface/resources/qml/+webengine/TabletBrowser.qml @@ -84,7 +84,7 @@ Item { } onFeaturePermissionRequested: { - grantFeaturePermission(securityOrigin, feature, true); + grantFeaturePermission(securityOrigin, feature, false); } onLoadingChanged: { diff --git a/interface/resources/qml/InteractiveWindow.qml b/interface/resources/qml/InteractiveWindow.qml index df3475ea7b..9136de9dcf 100644 --- a/interface/resources/qml/InteractiveWindow.qml +++ b/interface/resources/qml/InteractiveWindow.qml @@ -31,6 +31,8 @@ Windows.Window { signal selfDestruct(); property var flags: 0; + property var additionalFlags: 0; + property var overrideFlags: 0; property var source; property var dynamicContent; @@ -153,10 +155,11 @@ Windows.Window { Qt.WindowMaximizeButtonHint | Qt.WindowMinimizeButtonHint; // only use the always on top feature for non Windows OS - if (Qt.platform.os !== "windows" && (flags & Desktop.ALWAYS_ON_TOP)) { + if (Qt.platform.os !== "windows" && (root.additionalFlags & Desktop.ALWAYS_ON_TOP)) { nativeWindowFlags |= Qt.WindowStaysOnTopHint; } - nativeWindow.flags = nativeWindowFlags; + root.flags = root.overrideFlags || nativeWindowFlags; + nativeWindow.flags = root.flags; nativeWindow.x = interactiveWindowPosition.x; nativeWindow.y = interactiveWindowPosition.y; @@ -225,10 +228,41 @@ Windows.Window { // Handle message traffic from our loaded QML to the script that launched us signal sendToScript(var message); + // Children of this InteractiveWindow Item are able to request a new width and height + // for the parent Item (this one) and its associated C++ InteractiveWindow using these methods. + function onRequestNewWidth(newWidth) { + interactiveWindowSize.width = newWidth; + updateInteractiveWindowSizeForMode(); + } + function onRequestNewHeight(newWidth) { + interactiveWindowSize.width = newWidth; + updateInteractiveWindowSizeForMode(); + } + + // These signals are used to forward key-related events from the QML to the C++. + signal keyPressEvent(int key, int modifiers); + signal keyReleaseEvent(int key, int modifiers); + onDynamicContentChanged: { if (dynamicContent && dynamicContent.sendToScript) { dynamicContent.sendToScript.connect(sendToScript); } + + if (dynamicContent && dynamicContent.requestNewWidth) { + dynamicContent.requestNewWidth.connect(onRequestNewWidth); + } + + if (dynamicContent && dynamicContent.requestNewHeight) { + dynamicContent.requestNewHeight.connect(onRequestNewHeight); + } + + if (dynamicContent && dynamicContent.keyPressEvent) { + dynamicContent.keyPressEvent.connect(keyPressEvent); + } + + if (dynamicContent && dynamicContent.keyReleaseEvent) { + dynamicContent.keyReleaseEvent.connect(keyReleaseEvent); + } } onInteractiveWindowVisibleChanged: { @@ -283,7 +317,7 @@ Windows.Window { // set invisible on close, to make it not re-appear unintended after switching PresentationMode interactiveWindowVisible = false; - if ((flags & Desktop.CLOSE_BUTTON_HIDES) !== Desktop.CLOSE_BUTTON_HIDES) { + if ((root.flags & Desktop.CLOSE_BUTTON_HIDES) !== Desktop.CLOSE_BUTTON_HIDES) { selfDestruct(); } } diff --git a/interface/resources/qml/controls/+webengine/FlickableWebViewCore.qml b/interface/resources/qml/controls/+webengine/FlickableWebViewCore.qml index 823d0107a2..56eecf3f46 100644 --- a/interface/resources/qml/controls/+webengine/FlickableWebViewCore.qml +++ b/interface/resources/qml/controls/+webengine/FlickableWebViewCore.qml @@ -141,7 +141,7 @@ Item { } onFeaturePermissionRequested: { - grantFeaturePermission(securityOrigin, feature, true); + grantFeaturePermission(securityOrigin, feature, false); } //disable popup diff --git a/interface/resources/qml/controlsUit/+webengine/BaseWebView.qml b/interface/resources/qml/controlsUit/+webengine/BaseWebView.qml index fdd9c12220..faf80b2b11 100644 --- a/interface/resources/qml/controlsUit/+webengine/BaseWebView.qml +++ b/interface/resources/qml/controlsUit/+webengine/BaseWebView.qml @@ -35,4 +35,8 @@ WebEngineView { } WebSpinner { } + + onFeaturePermissionRequested: { + grantFeaturePermission(securityOrigin, feature, false); + } } diff --git a/interface/resources/qml/hifi/NameCard.qml b/interface/resources/qml/hifi/NameCard.qml index 7e8218b7df..2cf07e32bf 100644 --- a/interface/resources/qml/hifi/NameCard.qml +++ b/interface/resources/qml/hifi/NameCard.qml @@ -400,7 +400,8 @@ Item { size: 24; x: 120 anchors.verticalCenter: nameCardConnectionInfoImage.verticalCenter - anchors.left: has3DHTML ? nameCardConnectionInfoText.right + 10 : avatarImage.right + anchors.left: has3DHTML ? nameCardConnectionInfoText.right : avatarImage.right + anchors.leftMargin: has3DHTML ? 10 : 0 } MouseArea { anchors.fill:nameCardRemoveConnectionImage diff --git a/interface/resources/qml/hifi/simplifiedUI/emoteApp/bar/EmoteAppBar.qml b/interface/resources/qml/hifi/simplifiedUI/emoteApp/bar/EmoteAppBar.qml new file mode 100644 index 0000000000..fd1d245033 --- /dev/null +++ b/interface/resources/qml/hifi/simplifiedUI/emoteApp/bar/EmoteAppBar.qml @@ -0,0 +1,101 @@ +// +// EmoteAppBar.qml +// +// Created by Zach Fox on 2019-07-08 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.10 +import QtQuick.Controls 2.3 +import "../../simplifiedConstants" as SimplifiedConstants +import "../../simplifiedControls" as SimplifiedControls +import stylesUit 1.0 as HifiStylesUit +import TabletScriptingInterface 1.0 + +Rectangle { + id: root + color: simplifiedUI.colors.white + anchors.fill: parent + + property int originalWidth: 48 + property int hoveredWidth: 480 + property int requestedWidth + + onRequestedWidthChanged: { + root.requestNewWidth(root.requestedWidth); + } + + Behavior on requestedWidth { + enabled: true + SmoothedAnimation { duration: 220 } + } + + SimplifiedConstants.SimplifiedConstants { + id: simplifiedUI + } + + MouseArea { + anchors.fill: parent + hoverEnabled: enabled + onEntered: { + Tablet.playSound(TabletEnums.ButtonHover); + root.requestedWidth = root.hoveredWidth; + } + onExited: { + Tablet.playSound(TabletEnums.ButtonClick); + root.requestedWidth = root.originalWidth; + } + } + + Rectangle { + id: mainEmojiContainer + z: 2 + color: simplifiedUI.colors.darkBackground + anchors.top: parent.top + anchors.left: parent.left + height: parent.height + width: root.originalWidth + + HifiStylesUit.GraphikRegular { + text: "😊" + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenterOffset: -2 + anchors.verticalCenterOffset: -2 + horizontalAlignment: Text.AlignHCenter + size: 26 + color: simplifiedUI.colors.text.almostWhite + } + } + + Rectangle { + id: drawerContainer + z: 1 + color: simplifiedUI.colors.white + anchors.top: parent.top + anchors.right: parent.right + height: parent.height + width: root.hoveredWidth + + HifiStylesUit.GraphikRegular { + text: "Emotes go here." + anchors.fill: parent + horizontalAlignment: Text.AlignHCenter + size: 20 + color: simplifiedUI.colors.text.black + } + } + + function fromScript(message) { + switch (message.method) { + default: + console.log('EmoteAppBar.qml: Unrecognized message from JS'); + break; + } + } + signal sendToScript(var message); + signal requestNewWidth(int newWidth); +} diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml index c546af218b..15f4c42d39 100644 --- a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml +++ b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/InputDeviceButton.qml @@ -33,6 +33,7 @@ Rectangle { readonly property string unmutedIcon: "images/mic-unmute-i.svg" readonly property string mutedIcon: "images/mic-mute-i.svg" readonly property string pushToTalkIcon: "images/mic-ptt-i.svg" + readonly property string pushToTalkMutedIcon: "images/mic-ptt-mute-i.svg" readonly property string clippingIcon: "images/mic-clip-i.svg" readonly property string gatedIcon: "images/mic-gate-i.svg" @@ -48,18 +49,6 @@ Rectangle { } } - opacity: 0.7 - - onLevelChanged: { - var rectOpacity = (muted && (level >= userSpeakingLevel)) ? 1.0 : 0.7; - if (pushToTalk && !pushingToTalk) { - rectOpacity = (mouseArea.containsMouse) ? 1.0 : 0.7; - } else if (mouseArea.containsMouse && rectOpacity != 1.0) { - rectOpacity = 1.0; - } - micBar.opacity = rectOpacity; - } - color: "#00000000" MouseArea { @@ -116,82 +105,84 @@ Rectangle { Item { id: icon anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.horizontalCenter + anchors.horizontalCenter: parent.horizontalCenter anchors.rightMargin: 2 - width: 13 - height: 21 + width: pushToTalk ? 16 : (muted ? 20 : 16) + height: 22 Item { anchors.fill: parent - opacity: mouseArea.containsMouse ? 1.0 : 0.7 Image { id: image + visible: false source: (pushToTalk) ? pushToTalkIcon : muted ? mutedIcon : clipping ? clippingIcon : gated ? gatedIcon : unmutedIcon anchors.fill: parent - fillMode: Image.PreserveAspectFit } ColorOverlay { + opacity: mouseArea.containsMouse ? 1.0 : 0.7 + visible: level === 0 || micBar.muted || micBar.clipping id: imageOverlay anchors { fill: image } source: image - color: pushToTalk ? (pushingToTalk ? colors.unmutedColor : colors.mutedColor) : colors.icon + color: pushToTalk ? (pushingToTalk ? colors.icon : colors.mutedColor) : colors.icon + } + + OpacityMask { + id: bar + visible: level > 0 && !micBar.muted && !micBar.clipping + anchors.fill: meterGradient + source: meterGradient + maskSource: image + } + + LinearGradient { + id: meterGradient + anchors { fill: parent } + visible: false + start: Qt.point(0, 0) + end: Qt.point(0, parent.height) + rotation: 180 + gradient: Gradient { + GradientStop { + position: 1.0 + color: colors.greenStart + } + GradientStop { + position: 0.5 + color: colors.greenEnd + } + GradientStop { + position: 0.0 + color: colors.yellow + } + } } } - } - Item { - id: bar - - anchors.verticalCenter: parent.verticalCenter - anchors.left: parent.horizontalCenter - anchors.leftMargin: 2 - - width: 4 - height: 21 - - Rectangle { // base - id: baseBar - radius: 4 - anchors { fill: parent } - color: colors.gutter - } - - Rectangle { // mask - id: mask - height: micBar.muted ? parent.height : parent.height * level - color: micBar.muted ? colors.mutedColor : "white" + Item { width: parent.width - radius: 5 - anchors { - bottom: parent.bottom - bottomMargin: 0 - left: parent.left - leftMargin: 0 + height: parent.height - parent.height * level + anchors.top: parent.top + anchors.left: parent.left + clip:true + Image { + id: maskImage + visible: false + source: (pushToTalk) ? pushToTalkIcon : muted ? mutedIcon : + clipping ? clippingIcon : gated ? gatedIcon : unmutedIcon + anchors.top: parent.top + anchors.left: parent.left + width: parent.width + height: parent.parent.height } - } - - LinearGradient { - anchors { fill: mask } - visible: mask.visible && !micBar.muted - source: mask - start: Qt.point(0, 0) - end: Qt.point(0, bar.height) - rotation: 180 - gradient: Gradient { - GradientStop { - position: 0.0 - color: colors.greenStart - } - GradientStop { - position: 0.5 - color: colors.greenEnd - } - GradientStop { - position: 1.0 - color: colors.yellow - } + + ColorOverlay { + visible: level > 0 && !micBar.muted && !micBar.clipping + anchors { fill: maskImage } + source: maskImage + color: "#b2b2b2" } } } diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-clip-i.svg b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-clip-i.svg index 8b694c7f3d..f16b9e1a56 100644 --- a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-clip-i.svg +++ b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-clip-i.svg @@ -1,20 +1,14 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - + + + + + + + + diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-gate-i.svg b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-gate-i.svg index ac70ce66cb..56e0e1df57 100644 --- a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-gate-i.svg +++ b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-gate-i.svg @@ -1,13 +1,11 @@ - - - - - - image/svg+xml - - - - - - + + + + diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-mute-a.svg b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-mute-a.svg deleted file mode 100644 index eb36c2dd55..0000000000 --- a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-mute-a.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - image/svg+xml - - - - - - - diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-mute-i.svg b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-mute-i.svg index ebca81f370..a00b7f9a9c 100644 --- a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-mute-i.svg +++ b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-mute-i.svg @@ -1,13 +1,13 @@ - - - - - - image/svg+xml - - - - - - + + + + diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-ptt-a.svg b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-ptt-a.svg deleted file mode 100644 index 3ce7c0ca51..0000000000 --- a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-ptt-a.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - image/svg+xml - - mic-ptt-a - - - - - - - mic-ptt-a - - diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-ptt-i.svg b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-ptt-i.svg index 3bf1f1bf9e..7dd65c96a0 100644 --- a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-ptt-i.svg +++ b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-ptt-i.svg @@ -1,8 +1,16 @@ - - -image/svg+xml - - + + + + diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-ptt-mute-i.svg b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-ptt-mute-i.svg new file mode 100644 index 0000000000..fef3e533b4 --- /dev/null +++ b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-ptt-mute-i.svg @@ -0,0 +1,18 @@ + + + + + diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-unmute-a.svg b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-unmute-a.svg deleted file mode 100644 index 0bd0b0c238..0000000000 --- a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-unmute-a.svg +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - diff --git a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-unmute-i.svg b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-unmute-i.svg index 121873dd1b..dd8bfa087f 100644 --- a/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-unmute-i.svg +++ b/interface/resources/qml/hifi/simplifiedUI/inputDeviceButton/images/mic-unmute-i.svg @@ -1,13 +1,9 @@ - - - - - - image/svg+xml - - - - - - + + + + diff --git a/interface/resources/qml/hifi/simplifiedUI/settingsApp/about/About.qml b/interface/resources/qml/hifi/simplifiedUI/settingsApp/about/About.qml index 3e3758e7a8..d562aae70d 100644 --- a/interface/resources/qml/hifi/simplifiedUI/settingsApp/about/About.qml +++ b/interface/resources/qml/hifi/simplifiedUI/settingsApp/about/About.qml @@ -25,6 +25,14 @@ Flickable { if (visible) { root.contentX = 0; root.contentY = 0; + + // When the user clicks the About tab, refresh the audio I/O model so that + // the delegate Component.onCompleted handlers fire, which will update + // the text that appears in the About screen. + audioOutputDevices.model = undefined; + audioOutputDevices.model = AudioScriptingInterface.devices.output; + audioInputDevices.model = undefined; + audioInputDevices.model = AudioScriptingInterface.devices.input; } } @@ -47,8 +55,8 @@ Flickable { source: "images/logo.png" Layout.alignment: Qt.AlignHCenter Layout.topMargin: 16 - Layout.preferredWidth: 200 - Layout.preferredHeight: 150 + Layout.preferredWidth: 160 + Layout.preferredHeight: 120 fillMode: Image.PreserveAspectFit mipmap: true } @@ -195,6 +203,71 @@ Flickable { wrapMode: Text.Wrap } + // This is a bit of a hack to get the name of the currently-selected audio input device + // in the current mode (Desktop or VR). The reason this is necessary is because it seems to me like + // the only way one can get a human-readable list of the audio I/O devices is by using a ListView + // and grabbing the names from the AudioScriptingInterface; you can't do it using a ListModel. + // See `AudioDevices.h`, specifically the comment above the declaration of `QVariant data()`. + ListView { + id: audioInputDevices + visible: false + property string selectedInputDeviceName + Layout.preferredWidth: parent.width + Layout.preferredHeight: contentItem.height + interactive: false + delegate: Item { + Component.onCompleted: { + if (HMD.active && selectedHMD) { + audioInputDevices.selectedInputDeviceName = model.devicename + } else if (!HMD.active && selectedDesktop) { + audioInputDevices.selectedInputDeviceName = model.devicename + } + } + } + } + + HifiStylesUit.GraphikRegular { + text: "Audio Input: " + audioInputDevices.selectedInputDeviceName + Layout.maximumWidth: parent.width + height: paintedHeight + size: 16 + color: simplifiedUI.colors.text.white + wrapMode: Text.Wrap + } + + + // This is a bit of a hack to get the name of the currently-selected audio output device + // in the current mode (Desktop or VR). The reason this is necessary is because it seems to me like + // the only way one can get a human-readable list of the audio I/O devices is by using a ListView + // and grabbing the names from the AudioScriptingInterface; you can't do it using a ListModel. + // See `AudioDevices.h`, specifically the comment above the declaration of `QVariant data()`. + ListView { + id: audioOutputDevices + visible: false + property string selectedOutputDeviceName + Layout.preferredWidth: parent.width + Layout.preferredHeight: contentItem.height + interactive: false + delegate: Item { + Component.onCompleted: { + if (HMD.active && selectedHMD) { + audioOutputDevices.selectedOutputDeviceName = model.devicename + } else if (!HMD.active && selectedDesktop) { + audioOutputDevices.selectedOutputDeviceName = model.devicename + } + } + } + } + + HifiStylesUit.GraphikRegular { + text: "Audio Output: " + audioOutputDevices.selectedOutputDeviceName + Layout.maximumWidth: parent.width + height: paintedHeight + size: 16 + color: simplifiedUI.colors.text.white + wrapMode: Text.Wrap + } + SimplifiedControls.Button { Layout.topMargin: 8 width: 200 @@ -248,6 +321,8 @@ Flickable { textToCopy += "GPU: " + gpuModel + "\n"; textToCopy += "VR Hand Controllers: " + (PlatformInfo.hasRiftControllers() ? "Rift" : (PlatformInfo.hasViveControllers() ? "Vive" : "None")) + "\n"; + textToCopy += "Audio Input: " + audioInputDevices.selectedInputDeviceName + "\n"; + textToCopy += "Audio Output: " + audioOutputDevices.selectedOutputDeviceName + "\n"; textToCopy += "\n**All Platform Info**\n"; textToCopy += JSON.stringify(JSON.parse(PlatformInfo.getPlatform()), null, 4); diff --git a/interface/resources/qml/hifi/simplifiedUI/settingsApp/audio/Audio.qml b/interface/resources/qml/hifi/simplifiedUI/settingsApp/audio/Audio.qml index 68a8fa49da..8827bb3834 100644 --- a/interface/resources/qml/hifi/simplifiedUI/settingsApp/audio/Audio.qml +++ b/interface/resources/qml/hifi/simplifiedUI/settingsApp/audio/Audio.qml @@ -182,6 +182,7 @@ Flickable { ColumnLayout { id: micControlsSwitchGroup + Layout.preferredWidth: parent.width Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin SimplifiedControls.Switch { @@ -205,6 +206,22 @@ Flickable { AudioScriptingInterface.pushToTalkDesktop = !AudioScriptingInterface.pushToTalkDesktop; } } + + SimplifiedControls.Switch { + id: attenuateOutputSwitch + enabled: AudioScriptingInterface.pushToTalkDesktop + Layout.preferredHeight: 18 + Layout.preferredWidth: parent.width + labelTextOn: "Reduce volume of other sounds while I'm pushing-to-talk" + checked: AudioScriptingInterface.pushingToTalkOutputGainDesktop !== 0.0 + onClicked: { + if (AudioScriptingInterface.pushingToTalkOutputGainDesktop === 0.0) { + AudioScriptingInterface.pushingToTalkOutputGainDesktop = -20.0; + } else { + AudioScriptingInterface.pushingToTalkOutputGainDesktop = 0.0; + } + } + } } } diff --git a/interface/resources/qml/hifi/simplifiedUI/settingsApp/vr/VR.qml b/interface/resources/qml/hifi/simplifiedUI/settingsApp/vr/VR.qml index c1dc3888e2..d7e85c7f68 100644 --- a/interface/resources/qml/hifi/simplifiedUI/settingsApp/vr/VR.qml +++ b/interface/resources/qml/hifi/simplifiedUI/settingsApp/vr/VR.qml @@ -171,6 +171,7 @@ Flickable { ColumnLayout { id: micControlsSwitchGroup + Layout.preferredWidth: parent.width Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin SimplifiedControls.Switch { diff --git a/interface/resources/qml/hifi/simplifiedUI/simplifiedConstants/SimplifiedConstants.qml b/interface/resources/qml/hifi/simplifiedUI/simplifiedConstants/SimplifiedConstants.qml index fb09a7ae1d..bc27dbad5f 100644 --- a/interface/resources/qml/hifi/simplifiedUI/simplifiedConstants/SimplifiedConstants.qml +++ b/interface/resources/qml/hifi/simplifiedUI/simplifiedConstants/SimplifiedConstants.qml @@ -18,6 +18,7 @@ QtObject { readonly property color white: "#FFFFFF" readonly property color lightBlue: "#00B4EF" readonly property color lightBlueHover: "#3dcfff" + readonly property color black: "#000000" } readonly property QtObject controls: QtObject { @@ -72,10 +73,14 @@ QtObject { readonly property color border: "#00B4EF" } } + readonly property QtObject text: QtObject { + readonly property color enabled: "#FFFFFF" + readonly property color disabled: "#8F8F8F" + } } readonly property QtObject simplifiedSwitch: QtObject { readonly property QtObject background: QtObject { - readonly property color disabled: "#616161" + readonly property color disabled: "#2B2B2B" readonly property color off: "#616161" readonly property color hover: "#616161" readonly property color pressed: "#616161" diff --git a/interface/resources/qml/hifi/simplifiedUI/simplifiedControls/Slider.qml b/interface/resources/qml/hifi/simplifiedUI/simplifiedControls/Slider.qml index 38b114e9d2..9397963fbf 100644 --- a/interface/resources/qml/hifi/simplifiedUI/simplifiedControls/Slider.qml +++ b/interface/resources/qml/hifi/simplifiedUI/simplifiedControls/Slider.qml @@ -44,7 +44,7 @@ Item { anchors.bottom: parent.bottom horizontalAlignment: Text.AlignRight visible: sliderText.text != "" - color: simplifiedUI.colors.text.white + color: root.enabled ? simplifiedUI.colors.controls.slider.text.enabled : simplifiedUI.colors.controls.slider.text.disabled size: simplifiedUI.sizes.controls.slider.labelTextSize } diff --git a/interface/resources/qml/hifi/simplifiedUI/simplifiedControls/Switch.qml b/interface/resources/qml/hifi/simplifiedUI/simplifiedControls/Switch.qml index 9377dba9e1..bbfaa1ef1a 100644 --- a/interface/resources/qml/hifi/simplifiedUI/simplifiedControls/Switch.qml +++ b/interface/resources/qml/hifi/simplifiedUI/simplifiedControls/Switch.qml @@ -54,6 +54,7 @@ Item { innerSwitchHandle.color = simplifiedUI.colors.controls.simplifiedSwitch.handle.disabled; return; } + if (originalSwitch.checked) { if (originalSwitch.hovered) { innerSwitchHandle.color = simplifiedUI.colors.controls.simplifiedSwitch.handle.hover; @@ -69,6 +70,10 @@ Item { } } + onEnabledChanged: { + originalSwitch.changeColor(); + } + onCheckedChanged: { originalSwitch.changeColor(); } @@ -88,7 +93,8 @@ Item { background: Rectangle { id: switchBackground anchors.verticalCenter: parent.verticalCenter - color: originalSwitch.checked ? simplifiedUI.colors.controls.simplifiedSwitch.background.on : simplifiedUI.colors.controls.simplifiedSwitch.background.off + color: originalSwitch.enabled ? (originalSwitch.checked ? simplifiedUI.colors.controls.simplifiedSwitch.background.on : + simplifiedUI.colors.controls.simplifiedSwitch.background.off) : simplifiedUI.colors.controls.simplifiedSwitch.background.disabled width: originalSwitch.width height: simplifiedUI.sizes.controls.simplifiedSwitch.switchBackgroundHeight radius: height/2 @@ -113,7 +119,7 @@ Item { height: width radius: width/2 color: "transparent" - border.width: simplifiedUI.sizes.controls.simplifiedSwitch.switchHandleBorderSize + border.width: originalSwitch.enabled ? simplifiedUI.sizes.controls.simplifiedSwitch.switchHandleBorderSize : 0 border.color: simplifiedUI.colors.controls.simplifiedSwitch.handle.activeBorder } @@ -124,7 +130,7 @@ Item { height: width radius: width/2 color: simplifiedUI.colors.controls.simplifiedSwitch.handle.off - border.width: originalSwitch.pressed || originalSwitch.checked ? simplifiedUI.sizes.controls.simplifiedSwitch.switchHandleBorderSize : 0 + border.width: (originalSwitch.pressed || originalSwitch.checked) && originalSwitch.enabled ? simplifiedUI.sizes.controls.simplifiedSwitch.switchHandleBorderSize : 0 border.color: originalSwitch.pressed ? simplifiedUI.colors.controls.simplifiedSwitch.handle.activeBorder : simplifiedUI.colors.controls.simplifiedSwitch.handle.checkedBorder Component.onCompleted: { @@ -145,7 +151,7 @@ Item { id: labelOff text: "" size: simplifiedUI.sizes.controls.simplifiedSwitch.labelTextSize - color: originalSwitch.checked ? simplifiedUI.colors.controls.simplifiedSwitch.text.off : simplifiedUI.colors.controls.simplifiedSwitch.text.on + color: originalSwitch.checked && !originalSwitch.enabled ? simplifiedUI.colors.controls.simplifiedSwitch.text.off : simplifiedUI.colors.controls.simplifiedSwitch.text.on anchors.top: parent.top anchors.topMargin: -2 // Necessary for text alignment anchors.bottom: parent.bottom @@ -193,7 +199,7 @@ Item { id: labelOn text: "" size: simplifiedUI.sizes.controls.simplifiedSwitch.labelTextSize - color: originalSwitch.checked ? simplifiedUI.colors.controls.simplifiedSwitch.text.on : simplifiedUI.colors.controls.simplifiedSwitch.text.off + color: originalSwitch.checked && originalSwitch.enabled ? simplifiedUI.colors.controls.simplifiedSwitch.text.on : simplifiedUI.colors.controls.simplifiedSwitch.text.off anchors.top: parent.top anchors.topMargin: -2 // Necessary for text alignment anchors.left: parent.left diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml b/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml index 42d53d3f79..822e485940 100644 --- a/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml +++ b/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml @@ -76,10 +76,20 @@ Rectangle { return; } - if (walletStatus === 5) { - topBarInventoryModel.getFirstPage(); - } else { - // Show some error to the user + switch (walletStatus) { + case 1: + var randomNumber = Math.floor(Math.random() * 34) + 1; + var securityImagePath = "images/" + randomNumber.toString().padStart(2, '0') + ".jpg"; + Commerce.getWalletAuthenticatedStatus(); // before writing security image, ensures that salt/account password is set. + Commerce.chooseSecurityImage(securityImagePath); + Commerce.generateKeyPair() + Commerce.getWalletStatus(); + break; + case 5: + topBarInventoryModel.getFirstPage(); + break; + default: + console.log('WARNING: SimplifiedTopBar.qml walletStatusResult:', walletStatus); } } @@ -141,7 +151,7 @@ Rectangle { id: avatarButtonContainer anchors.verticalCenter: parent.verticalCenter anchors.left: parent.left - anchors.leftMargin: 16 + anchors.leftMargin: 2 width: 48 height: width @@ -210,7 +220,7 @@ Rectangle { id: inputDeviceButton anchors.verticalCenter: parent.verticalCenter anchors.left: avatarButtonContainer.right - anchors.leftMargin: 6 + anchors.leftMargin: 2 width: 32 height: width } @@ -220,7 +230,7 @@ Rectangle { id: outputDeviceButtonContainer anchors.verticalCenter: parent.verticalCenter anchors.left: inputDeviceButton.right - anchors.leftMargin: 2 + anchors.leftMargin: 7 width: 32 height: width @@ -232,9 +242,8 @@ Rectangle { AudioScriptingInterface.systemInjectorGain === simplifiedUI.numericConstants.mutedValue source: outputDeviceButton.outputMuted ? "./images/outputDeviceMuted.svg" : "./images/outputDeviceLoud.svg" anchors.centerIn: parent - width: 20 - height: 20 - fillMode: Image.PreserveAspectFit + width: outputDeviceButton.outputMuted ? 25 : 26 + height: 22 visible: false } @@ -283,7 +292,7 @@ Rectangle { id: statusButton property string currentStatus anchors.centerIn: parent - width: 15 + width: 22 height: width radius: width/2 visible: false @@ -304,6 +313,21 @@ Rectangle { } } + Image { + id: statusIcon + source: statusButton.currentStatus === "available" ? "images/statusPresent.svg" : "images/statusAway.svg" + anchors.centerIn: parent + width: statusButton.currentStatus === "busy" ? 13 : 14 + height: statusButton.currentStatus === "busy" ? 2 : 10 + } + + ColorOverlay { + anchors.fill: statusIcon + opacity: statusButton.currentStatus ? (statusButtonMouseArea.containsMouse ? 1.0 : 0.7) : 0.7 + source: statusIcon + color: "#ffffff" + } + MouseArea { id: statusButtonMouseArea anchors.fill: parent @@ -329,8 +353,8 @@ Rectangle { id: hmdButtonContainer anchors.verticalCenter: parent.verticalCenter anchors.right: settingsButtonContainer.left - anchors.rightMargin: 14 - width: 32 + anchors.rightMargin: 8 + width: 48 height: width visible: false @@ -338,9 +362,8 @@ Rectangle { id: displayModeImage source: HMD.active ? "./images/desktopMode.svg" : "./images/vrMode.svg" anchors.centerIn: parent - width: 29 - height: 16 - fillMode: Image.PreserveAspectFit + width: HMD.active ? 25 : 43 + height: 22 visible: false } @@ -399,17 +422,16 @@ Rectangle { id: settingsButtonContainer anchors.verticalCenter: parent.verticalCenter anchors.right: parent.right - anchors.rightMargin: 16 - width: 32 + anchors.rightMargin: 3 + width: 36 height: width Image { id: settingsButtonImage source: "./images/settings.svg" anchors.centerIn: parent - width: 20 - height: 20 - fillMode: Image.PreserveAspectFit + width: 22 + height: 22 visible: false } diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/images/desktopMode.svg b/interface/resources/qml/hifi/simplifiedUI/topBar/images/desktopMode.svg index 8b04caca88..dfb1a1a662 100644 --- a/interface/resources/qml/hifi/simplifiedUI/topBar/images/desktopMode.svg +++ b/interface/resources/qml/hifi/simplifiedUI/topBar/images/desktopMode.svg @@ -1,13 +1,8 @@ - - - - - - image/svg+xml - - - - - - + + + + diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/images/outputDeviceLoud.svg b/interface/resources/qml/hifi/simplifiedUI/topBar/images/outputDeviceLoud.svg index ebd844c471..798ce62ccd 100644 --- a/interface/resources/qml/hifi/simplifiedUI/topBar/images/outputDeviceLoud.svg +++ b/interface/resources/qml/hifi/simplifiedUI/topBar/images/outputDeviceLoud.svg @@ -1,3 +1,14 @@ - - - + + + + + diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/images/outputDeviceMuted.svg b/interface/resources/qml/hifi/simplifiedUI/topBar/images/outputDeviceMuted.svg index 4188175c31..9b7e3ad613 100644 --- a/interface/resources/qml/hifi/simplifiedUI/topBar/images/outputDeviceMuted.svg +++ b/interface/resources/qml/hifi/simplifiedUI/topBar/images/outputDeviceMuted.svg @@ -1,14 +1,14 @@ - - - - - - image/svg+xml - - - - - - - + + + + diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/images/settings.svg b/interface/resources/qml/hifi/simplifiedUI/topBar/images/settings.svg index 04a031d498..910ef353e1 100644 --- a/interface/resources/qml/hifi/simplifiedUI/topBar/images/settings.svg +++ b/interface/resources/qml/hifi/simplifiedUI/topBar/images/settings.svg @@ -1,13 +1,17 @@ - - - - - - image/svg+xml - - - - - - + + + + diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/images/status.svg b/interface/resources/qml/hifi/simplifiedUI/topBar/images/status.svg deleted file mode 100644 index ebd844c471..0000000000 --- a/interface/resources/qml/hifi/simplifiedUI/topBar/images/status.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/images/statusAway.svg b/interface/resources/qml/hifi/simplifiedUI/topBar/images/statusAway.svg new file mode 100644 index 0000000000..d5b4798d9e --- /dev/null +++ b/interface/resources/qml/hifi/simplifiedUI/topBar/images/statusAway.svg @@ -0,0 +1,9 @@ + + + + + + diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/images/statusPresent.svg b/interface/resources/qml/hifi/simplifiedUI/topBar/images/statusPresent.svg new file mode 100644 index 0000000000..af7649ba78 --- /dev/null +++ b/interface/resources/qml/hifi/simplifiedUI/topBar/images/statusPresent.svg @@ -0,0 +1,7 @@ + + + + + diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/images/vrMode.svg b/interface/resources/qml/hifi/simplifiedUI/topBar/images/vrMode.svg index 57b564813d..f19989c0b1 100644 --- a/interface/resources/qml/hifi/simplifiedUI/topBar/images/vrMode.svg +++ b/interface/resources/qml/hifi/simplifiedUI/topBar/images/vrMode.svg @@ -1,13 +1,10 @@ - - - - - - image/svg+xml - - - - - - + + + + diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index efb09baa0f..2fdaec40ac 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -548,6 +548,13 @@ public: return true; } + if (message->message == WM_POWERBROADCAST) { + if (message->wParam == PBT_APMRESUMEAUTOMATIC) { + qCInfo(interfaceapp) << "Waking up from sleep or hybernation."; + QMetaObject::invokeMethod(DependencyManager::get().data(), "noteAwakening", Qt::QueuedConnection); + } + } + if (message->message == WM_COPYDATA) { COPYDATASTRUCT* pcds = (COPYDATASTRUCT*)(message->lParam); QUrl url = QUrl((const char*)(pcds->lpData)); @@ -832,6 +839,8 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { QCoreApplication::addLibraryPath(audioDLLPath); #endif + QString defaultScriptsOverrideOption = getCmdOption(argc, constArgv, "--defaultScriptsOverride"); + DependencyManager::registerInheritance(); DependencyManager::registerInheritance(); DependencyManager::registerInheritance(); @@ -853,7 +862,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { DependencyManager::set(std::bind(&Application::getUserAgent, qApp)); #endif DependencyManager::set(); - DependencyManager::set(ScriptEngine::CLIENT_SCRIPT); + DependencyManager::set(ScriptEngine::CLIENT_SCRIPT, defaultScriptsOverrideOption); DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); @@ -878,6 +887,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); + DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); @@ -1177,6 +1187,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo } auto accountManager = DependencyManager::get(); + // set the account manager's root URL and trigger a login request if we don't have the access token + accountManager->setIsAgent(true); + accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL()); + if (!accountManager->hasKeyPair()) { + accountManager->generateNewUserKeypair(); + } + #ifndef Q_OS_ANDROID _logger->setSessionID(accountManager->getSessionID()); #endif @@ -1324,10 +1341,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo #endif connect(accountManager.data(), &AccountManager::usernameChanged, this, &Application::updateWindowTitle); - // set the account manager's root URL and trigger a login request if we don't have the access token - accountManager->setIsAgent(true); - accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL()); - // use our MyAvatar position and quat for address manager path addressManager->setPositionGetter([] { auto avatarManager = DependencyManager::get(); @@ -1344,9 +1357,22 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo connect(this, &QCoreApplication::aboutToQuit, addressManager.data(), &AddressManager::storeCurrentAddress); connect(this, &Application::activeDisplayPluginChanged, this, &Application::updateThreadPoolCount); - connect(this, &Application::activeDisplayPluginChanged, this, [](){ + connect(this, &Application::activeDisplayPluginChanged, this, [=](){ qApp->setProperty(hifi::properties::HMD, qApp->isHMDMode()); auto displayPlugin = qApp->getActiveDisplayPlugin(); + + if (displayPlugin->isHmd()) { + if (_preferredCursor.get() == Cursor::Manager::getIconName(Cursor::Icon::RETICLE)) { + setPreferredCursor(Cursor::Manager::getIconName(Cursor::Icon::RETICLE)); + } + else { + setPreferredCursor(Cursor::Manager::getIconName(Cursor::Icon::ARROW)); + } + } + else { + setPreferredCursor(Cursor::Manager::getIconName(Cursor::Icon::SYSTEM)); + } + setCrashAnnotation("display_plugin", displayPlugin->getName().toStdString()); setCrashAnnotation("hmd", displayPlugin->isHmd() ? "1" : "0"); }); @@ -1377,6 +1403,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo connect(myAvatar.get(), &MyAvatar::positionGoneTo, DependencyManager::get().data(), &AddressManager::storeCurrentAddress); + connect(myAvatar.get(), &MyAvatar::positionGoneTo, this, [this] { + if (!_physicsEnabled) { + // when we arrive somewhere without physics enabled --> startSafeLanding + _octreeProcessor.startSafeLanding(); + } + }, Qt::QueuedConnection); + connect(myAvatar.get(), &MyAvatar::skeletonModelURLChanged, [](){ QUrl avatarURL = qApp->getMyAvatar()->getSkeletonModelURL(); setCrashAnnotation("avatar", avatarURL.toString().toStdString()); @@ -1444,6 +1477,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo _saveAvatarOverrideUrl = true; } + // setDefaultFormat has no effect after the platform window has been created, so call it here. + QSurfaceFormat::setDefaultFormat(getDefaultOpenGLSurfaceFormat()); + _glWidget = new GLCanvas(); getApplicationCompositor().setRenderingWidget(_glWidget); _window->setCentralWidget(_glWidget); @@ -2501,6 +2537,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo pauseUntilLoginDetermined(); } +void Application::setFailedToConnectToEntityServer() { + _failedToConnectToEntityServer = true; +} + void Application::updateVerboseLogging() { auto menu = Menu::getInstance(); if (!menu) { @@ -2715,6 +2755,7 @@ void Application::cleanupBeforeQuit() { // Clear any queued processing (I/O, FBX/OBJ/Texture parsing) QThreadPool::globalInstance()->clear(); + QThreadPool::globalInstance()->waitForDone(); DependencyManager::destroy(); @@ -2843,6 +2884,7 @@ Application::~Application() { DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); + DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); @@ -2878,6 +2920,16 @@ Application::~Application() { // Can't log to file past this point, FileLogger about to be deleted qInstallMessageHandler(LogHandler::verboseMessageHandler); + +#ifdef Q_OS_MAC + // Clear the event queue before application is totally destructed. + // This will drain the messasge queue of pending "deleteLaters" queued up + // during shutdown of the script engines. + // We do this here because there is a possiblty that [NSApplication terminate:] + // will be called during processEvents which will invoke all static destructors. + // We want to postpone this utill the last possible moment. + QCoreApplication::processEvents(); +#endif } void Application::initializeGL() { @@ -3083,7 +3135,22 @@ void Application::showLoginScreen() { #endif } +static const QUrl AUTHORIZED_EXTERNAL_QML_SOURCE { "https://content.highfidelity.com/Experiences/Releases" }; + void Application::initializeUi() { + + // Allow remote QML content from trusted sources ONLY + { + auto defaultUrlValidator = OffscreenQmlSurface::getUrlValidator(); + auto newValidator = [=](const QUrl& url)->bool { + if (AUTHORIZED_EXTERNAL_QML_SOURCE.isParentOf(url)) { + return true; + } + return defaultUrlValidator(url); + }; + OffscreenQmlSurface::setUrlValidator(newValidator); + } + AddressBarDialog::registerType(); ErrorDialog::registerType(); LoginDialog::registerType(); @@ -4111,6 +4178,13 @@ bool Application::event(QEvent* event) { case QEvent::FocusOut: focusOutEvent(static_cast(event)); return true; + case QEvent::FocusIn: + { //testing to see if we can set focus when focus is not set to root window. + _glWidget->activateWindow(); + _glWidget->setFocus(); + return true; + } + case QEvent::TouchBegin: touchBeginEvent(static_cast(event)); event->accept(); @@ -4360,27 +4434,6 @@ void Application::keyPressEvent(QKeyEvent* event) { } break; - case Qt::Key_P: { - if (!isShifted && !isMeta && !isOption && !event->isAutoRepeat()) { - AudioInjectorOptions options; - options.localOnly = true; - options.positionSet = false; // system sound - options.stereo = true; - - Setting::Handle notificationSounds{ MenuOption::NotificationSounds, true }; - Setting::Handle notificationSoundSnapshot{ MenuOption::NotificationSoundsSnapshot, true }; - if (notificationSounds.get() && notificationSoundSnapshot.get()) { - if (_snapshotSoundInjector) { - DependencyManager::get()->setOptionsAndRestart(_snapshotSoundInjector, options); - } else { - _snapshotSoundInjector = DependencyManager::get()->playSound(_snapshotSound, options); - } - } - takeSnapshot(true); - } - break; - } - case Qt::Key_Apostrophe: { if (isMeta) { auto cursor = Cursor::Manager::instance().getCursor(); @@ -5072,7 +5125,7 @@ void Application::idle() { // If the offscreen Ui has something active that is NOT the root, then assume it has keyboard focus. if (offscreenUi && offscreenUi->getWindow()) { auto activeFocusItem = offscreenUi->getWindow()->activeFocusItem(); - if (_keyboardDeviceHasFocus && activeFocusItem != offscreenUi->getRootItem()) { + if (_keyboardDeviceHasFocus && (activeFocusItem != NULL && activeFocusItem != offscreenUi->getRootItem())) { _keyboardMouseDevice->pluginFocusOutEvent(); _keyboardDeviceHasFocus = false; synthesizeKeyReleasEvents(); @@ -5356,12 +5409,10 @@ void Application::loadSettings() { } bool isFirstPerson = false; - if (_firstRun.get()) { - // If this is our first run, and no preferred devices were set, default to - // an HMD device if available. + if (arguments().contains("--no-launcher")) { auto displayPlugins = pluginManager->getDisplayPlugins(); for (auto& plugin : displayPlugins) { - if (plugin->isHmd()) { + if (!plugin->isHmd()) { if (auto action = menu->getActionForOption(plugin->getName())) { action->setChecked(true); action->trigger(); @@ -5369,18 +5420,31 @@ void Application::loadSettings() { } } } - isFirstPerson = (qApp->isHMDMode()); - } else { - // if this is not the first run, the camera will be initialized differently depending on user settings - - if (qApp->isHMDMode()) { - // if the HMD is active, use first-person camera, unless the appropriate setting is checked - isFirstPerson = menu->isOptionChecked(MenuOption::FirstPersonHMD); + if (_firstRun.get()) { + // If this is our first run, and no preferred devices were set, default to + // an HMD device if available. + auto displayPlugins = pluginManager->getDisplayPlugins(); + for (auto& plugin : displayPlugins) { + if (plugin->isHmd()) { + if (auto action = menu->getActionForOption(plugin->getName())) { + action->setChecked(true); + action->trigger(); + break; + } + } + } + isFirstPerson = (qApp->isHMDMode()); } else { - // if HMD is not active, only use first person if the menu option is checked - isFirstPerson = menu->isOptionChecked(MenuOption::FirstPerson); + // if this is not the first run, the camera will be initialized differently depending on user settings + if (qApp->isHMDMode()) { + // if the HMD is active, use first-person camera, unless the appropriate setting is checked + isFirstPerson = menu->isOptionChecked(MenuOption::FirstPersonHMD); + } else { + // if HMD is not active, only use first person if the menu option is checked + isFirstPerson = menu->isOptionChecked(MenuOption::FirstPerson); + } } } @@ -5914,10 +5978,8 @@ void Application::resetPhysicsReadyInformation() { _gpuTextureMemSizeStabilityCount = 0; _gpuTextureMemSizeAtLastCheck = 0; _physicsEnabled = false; - _octreeProcessor.startEntitySequence(); } - void Application::reloadResourceCaches() { resetPhysicsReadyInformation(); @@ -5938,7 +6000,7 @@ void Application::reloadResourceCaches() { DependencyManager::get()->clear(); DependencyManager::get()->refreshAll(); DependencyManager::get()->refreshAll(); - MaterialCache::instance().refreshAll(); + DependencyManager::get()->refreshAll(); DependencyManager::get()->refreshAll(); ShaderCache::instance().refreshAll(); DependencyManager::get()->refreshAll(); @@ -6164,6 +6226,24 @@ void Application::updateSecondaryCameraViewFrustum() { static bool domainLoadingInProgress = false; +void Application::tryToEnablePhysics() { + bool enableInterstitial = DependencyManager::get()->getDomainHandler().getInterstitialModeEnabled(); + + if (gpuTextureMemSizeStable() || !enableInterstitial) { + _fullSceneCounterAtLastPhysicsCheck = _fullSceneReceivedCounter; + _lastQueriedViews.clear(); // Force new view. + + // process octree stats packets are sent in between full sends of a scene (this isn't currently true). + // We keep physics disabled until we've received a full scene and everything near the avatar in that + // scene is ready to compute its collision shape. + if (getMyAvatar()->isReadyForPhysics()) { + _physicsEnabled = true; + setIsInterstitialMode(false); + getMyAvatar()->updateMotionBehaviorFromMenu(); + } + } +} + void Application::update(float deltaTime) { PROFILE_RANGE_EX(app, __FUNCTION__, 0xffff0000, (uint64_t)_graphicsEngine._renderFrameCount + 1); @@ -6171,7 +6251,6 @@ void Application::update(float deltaTime) { return; } - if (!_physicsEnabled) { if (!domainLoadingInProgress) { PROFILE_ASYNC_BEGIN(app, "Scene Loading", ""); @@ -6180,24 +6259,16 @@ void Application::update(float deltaTime) { // we haven't yet enabled physics. we wait until we think we have all the collision information // for nearby entities before starting bullet up. - quint64 now = usecTimestampNow(); - if (isServerlessMode() || _octreeProcessor.isLoadSequenceComplete()) { - bool enableInterstitial = DependencyManager::get()->getDomainHandler().getInterstitialModeEnabled(); - - if (gpuTextureMemSizeStable() || !enableInterstitial) { - // we've received a new full-scene octree stats packet, or it's been long enough to try again anyway - _lastPhysicsCheckTime = now; - _fullSceneCounterAtLastPhysicsCheck = _fullSceneReceivedCounter; - _lastQueriedViews.clear(); // Force new view. - - // process octree stats packets are sent in between full sends of a scene (this isn't currently true). - // We keep physics disabled until we've received a full scene and everything near the avatar in that - // scene is ready to compute its collision shape. - if (getMyAvatar()->isReadyForPhysics()) { - _physicsEnabled = true; - setIsInterstitialMode(false); - getMyAvatar()->updateMotionBehaviorFromMenu(); - } + if (isServerlessMode()) { + tryToEnablePhysics(); + } else if (_failedToConnectToEntityServer) { + if (_octreeProcessor.safeLandingIsActive()) { + _octreeProcessor.stopSafeLanding(); + } + } else { + _octreeProcessor.updateSafeLanding(); + if (_octreeProcessor.safeLandingIsComplete()) { + tryToEnablePhysics(); } } } else if (domainLoadingInProgress) { @@ -6906,7 +6977,9 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType) { bool interstitialModeEnabled = DependencyManager::get()->getDomainHandler().getInterstitialModeEnabled(); ConicalViewFrustum sphericalView; - sphericalView.setSimpleRadius(INITIAL_QUERY_RADIUS); + AABox box = getMyAvatar()->getGlobalBoundingBox(); + float radius = glm::max(INITIAL_QUERY_RADIUS, 0.5f * glm::length(box.getDimensions())); + sphericalView.setPositionAndSimpleRadius(box.calcCenter(), radius); if (interstitialModeEnabled) { ConicalViewFrustum farView; @@ -7109,7 +7182,7 @@ void Application::clearDomainOctreeDetails(bool clearAll) { DependencyManager::get()->clearUnusedResources(); DependencyManager::get()->clearUnusedResources(); - MaterialCache::instance().clearUnusedResources(); + DependencyManager::get()->clearUnusedResources(); DependencyManager::get()->clearUnusedResources(); ShaderCache::instance().clearUnusedResources(); DependencyManager::get()->clearUnusedResources(); @@ -7142,13 +7215,17 @@ void Application::resettingDomain() { clearDomainOctreeDetails(false); } -void Application::nodeAdded(SharedNodePointer node) const { +void Application::nodeAdded(SharedNodePointer node) { if (node->getType() == NodeType::EntityServer) { - if (!_failedToConnectToEntityServer) { + if (_failedToConnectToEntityServer && !_entityServerConnectionTimer.isActive()) { + _failedToConnectToEntityServer = false; + _octreeProcessor.stopSafeLanding(); + _octreeProcessor.startSafeLanding(); + } else if (_entityServerConnectionTimer.isActive()) { _entityServerConnectionTimer.stop(); - _entityServerConnectionTimer.setInterval(ENTITY_SERVER_CONNECTION_TIMEOUT); - _entityServerConnectionTimer.start(); } + _entityServerConnectionTimer.setInterval(ENTITY_SERVER_CONNECTION_TIMEOUT); + _entityServerConnectionTimer.start(); } } @@ -7158,7 +7235,6 @@ void Application::nodeActivated(SharedNodePointer node) { #if !defined(DISABLE_QML) auto offscreenUi = getOffscreenUI(); - if (offscreenUi) { auto nodeList = DependencyManager::get(); @@ -7811,7 +7887,7 @@ void Application::showAssetServerWidget(QString filePath) { if (!hmd->getShouldShowTablet() && !isHMDMode()) { getOffscreenUI()->show(url, "AssetServer", startUpload); } else { - static const QUrl url("hifi/dialogs/TabletAssetServer.qml"); + static const QUrl url("qrc:///qml/hifi/dialogs/TabletAssetServer.qml"); if (!tablet->isPathLoaded(url)) { tablet->pushOntoStack(url); } @@ -8703,6 +8779,8 @@ bool Application::isThrottleRendering() const { bool Application::hasFocus() const { bool result = (QApplication::activeWindow() != nullptr); + + #if defined(Q_OS_WIN) // On Windows, QWidget::activateWindow() - as called in setFocus() - makes the application's taskbar icon flash but doesn't // take user focus away from their current window. So also check whether the application is the user's current foreground diff --git a/interface/src/Application.h b/interface/src/Application.h index 2cea492d56..2d6821bbd9 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -512,7 +512,7 @@ private slots: void loadSettings(); void saveSettings() const; - void setFailedToConnectToEntityServer() { _failedToConnectToEntityServer = true; } + void setFailedToConnectToEntityServer(); bool acceptSnapshot(const QString& urlString); bool askToSetAvatarUrl(const QString& url); @@ -527,7 +527,7 @@ private slots: void domainURLChanged(QUrl domainURL); void updateWindowTitle() const; - void nodeAdded(SharedNodePointer node) const; + void nodeAdded(SharedNodePointer node); void nodeActivated(SharedNodePointer node); void nodeKilled(SharedNodePointer node); static void packetSent(quint64 length); @@ -564,6 +564,7 @@ private: void cleanupBeforeQuit(); void idle(); + void tryToEnablePhysics(); void update(float deltaTime); // Various helper functions called during update() @@ -786,8 +787,6 @@ private: qint64 _gpuTextureMemSizeStabilityCount { 0 }; qint64 _gpuTextureMemSizeAtLastCheck { 0 }; - quint64 _lastPhysicsCheckTime { usecTimestampNow() }; // when did we last check to see if physics was ready - bool _keyboardDeviceHasFocus { true }; ConnectionMonitor _connectionMonitor; diff --git a/interface/src/PerformanceManager.cpp b/interface/src/PerformanceManager.cpp index 0a028f95cc..ec12ab0404 100644 --- a/interface/src/PerformanceManager.cpp +++ b/interface/src/PerformanceManager.cpp @@ -10,6 +10,8 @@ // #include "PerformanceManager.h" +#include +#include #include #include "scripting/RenderScriptingInterface.h" @@ -65,6 +67,19 @@ void PerformanceManager::applyPerformancePreset(PerformanceManager::PerformanceP // Ugly case that prevent us to run deferred everywhere... bool isDeferredCapable = platform::Profiler::isRenderMethodDeferredCapable(); + auto masterDisplay = platform::getDisplay(platform::getMasterDisplay()); + + // eval recommanded PPI and Scale + float recommandedPpiScale = 1.0f; + const float RECOMMANDED_PPI[] = { 200.0f, 120.f, 160.f, 250.f}; + if (!masterDisplay.empty() && masterDisplay.count(platform::keys::display::ppi)) { + float ppi = masterDisplay[platform::keys::display::ppi]; + // only scale if the actual ppi is higher than the recommended ppi + if (ppi > RECOMMANDED_PPI[preset]) { + // make sure the scale is no less than a quarter + recommandedPpiScale = std::max(0.25f, RECOMMANDED_PPI[preset] / (float) ppi); + } + } switch (preset) { case PerformancePreset::HIGH: @@ -72,17 +87,21 @@ void PerformanceManager::applyPerformancePreset(PerformanceManager::PerformanceP RenderScriptingInterface::RenderMethod::DEFERRED : RenderScriptingInterface::RenderMethod::FORWARD ) ); + RenderScriptingInterface::getInstance()->setViewportResolutionScale(recommandedPpiScale); + RenderScriptingInterface::getInstance()->setShadowsEnabled(true); qApp->getRefreshRateManager().setRefreshRateProfile(RefreshRateManager::RefreshRateProfile::REALTIME); DependencyManager::get()->setWorldDetailQuality(0.5f); - + break; case PerformancePreset::MID: RenderScriptingInterface::getInstance()->setRenderMethod((isDeferredCapable ? RenderScriptingInterface::RenderMethod::DEFERRED : RenderScriptingInterface::RenderMethod::FORWARD)); + RenderScriptingInterface::getInstance()->setViewportResolutionScale(recommandedPpiScale); + RenderScriptingInterface::getInstance()->setShadowsEnabled(false); qApp->getRefreshRateManager().setRefreshRateProfile(RefreshRateManager::RefreshRateProfile::INTERACTIVE); DependencyManager::get()->setWorldDetailQuality(0.5f); @@ -93,6 +112,8 @@ void PerformanceManager::applyPerformancePreset(PerformanceManager::PerformanceP RenderScriptingInterface::getInstance()->setShadowsEnabled(false); qApp->getRefreshRateManager().setRefreshRateProfile(RefreshRateManager::RefreshRateProfile::ECO); + RenderScriptingInterface::getInstance()->setViewportResolutionScale(recommandedPpiScale); + DependencyManager::get()->setWorldDetailQuality(0.75f); break; diff --git a/interface/src/avatar/AvatarActionHold.cpp b/interface/src/avatar/AvatarActionHold.cpp index 3ac9f63649..b7019bd6f0 100644 --- a/interface/src/avatar/AvatarActionHold.cpp +++ b/interface/src/avatar/AvatarActionHold.cpp @@ -457,12 +457,14 @@ bool AvatarActionHold::updateArguments(QVariantMap arguments) { * @property {number} timeScale=3.4e+38 - Controls how long it takes for the entity's position and rotation to catch up with * the target. The value is the time for the action to catch up to 1/e = 0.368 of the target value, where the action is * applied using an exponential decay. - * @property {boolean} kinematic=false - If true, the entity is made kinematic during the action; the entity won't - * lag behind the hand but constraint actions such as "hinge" won't act properly. - * @property {boolean} kinematicSetVelocity=false - If true and kinematic is true, the - * entity's velocity property will be set during the action, e.g., so that other scripts may use the value. - * @property {boolean} ignoreIK=false - If true, the entity follows the HMD controller rather than the avatar's - * hand. + * @property {boolean} kinematic=false - true if the entity is made kinematic during the action; the entity won't + * lag behind the hand but constraint actions such as "hinge" won't act properly. false if the + * entity is not made kinematic during the action + * @property {boolean} kinematicSetVelocity=false - true if, when kinematic is true, the + * entity's velocity will be set during the action, e.g., so that other scripts may use the value. false if + * the entity's velocity will not be set during the action. + * @property {boolean} ignoreIK=false - true if the entity follows the HMD controller, false if it + * follows the avatar's hand. */ QVariantMap AvatarActionHold::getArguments() { QVariantMap arguments = ObjectDynamic::getArguments(); diff --git a/interface/src/graphics/GraphicsEngine.cpp b/interface/src/graphics/GraphicsEngine.cpp index 7f9a612697..284118a52a 100644 --- a/interface/src/graphics/GraphicsEngine.cpp +++ b/interface/src/graphics/GraphicsEngine.cpp @@ -259,7 +259,7 @@ void GraphicsEngine::render_performFrame() { batch.enableSkybox(true); batch.enableStereo(isStereo); batch.setViewportTransform({ 0, 0, finalFramebuffer->getSize() }); - _splashScreen->render(batch, viewFrustum); + _splashScreen->render(batch, viewFrustum, renderArgs._renderMethod == RenderArgs::RenderMethod::FORWARD); }); } else { { diff --git a/interface/src/graphics/WorldBox.cpp b/interface/src/graphics/WorldBox.cpp index a28850207f..648d6d3177 100644 --- a/interface/src/graphics/WorldBox.cpp +++ b/interface/src/graphics/WorldBox.cpp @@ -108,8 +108,8 @@ void WorldBoxRenderData::renderWorldBox(RenderArgs* args, gpu::Batch& batch) { glm::vec3(HALF_TREE_SCALE, 0.0f, HALF_TREE_SCALE), GREY, geometryIds[17]); - - geometryCache->renderWireCubeInstance(args, batch, GREY4); + auto pipeline = geometryCache->getShapePipelinePointer(false, false, args->_renderMethod == render::Args::RenderMethod::FORWARD); + geometryCache->renderWireCubeInstance(args, batch, GREY4, pipeline); // Draw meter markers along the 3 axis to help with measuring things const float MARKER_DISTANCE = 1.0f; @@ -117,22 +117,22 @@ void WorldBoxRenderData::renderWorldBox(RenderArgs* args, gpu::Batch& batch) { transform = Transform().setScale(MARKER_RADIUS); batch.setModelTransform(transform); - geometryCache->renderSolidSphereInstance(args, batch, RED); + geometryCache->renderSolidSphereInstance(args, batch, RED, pipeline); transform = Transform().setTranslation(glm::vec3(MARKER_DISTANCE, 0.0f, 0.0f)).setScale(MARKER_RADIUS); batch.setModelTransform(transform); - geometryCache->renderSolidSphereInstance(args, batch, RED); + geometryCache->renderSolidSphereInstance(args, batch, RED, pipeline); transform = Transform().setTranslation(glm::vec3(0.0f, MARKER_DISTANCE, 0.0f)).setScale(MARKER_RADIUS); batch.setModelTransform(transform); - geometryCache->renderSolidSphereInstance(args, batch, GREEN); + geometryCache->renderSolidSphereInstance(args, batch, GREEN, pipeline); transform = Transform().setTranslation(glm::vec3(0.0f, 0.0f, MARKER_DISTANCE)).setScale(MARKER_RADIUS); batch.setModelTransform(transform); - geometryCache->renderSolidSphereInstance(args, batch, BLUE); + geometryCache->renderSolidSphereInstance(args, batch, BLUE, pipeline); transform = Transform().setTranslation(glm::vec3(MARKER_DISTANCE, 0.0f, MARKER_DISTANCE)).setScale(MARKER_RADIUS); batch.setModelTransform(transform); - geometryCache->renderSolidSphereInstance(args, batch, GREY); + geometryCache->renderSolidSphereInstance(args, batch, GREY, pipeline); } diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 3fd65f452c..f6ce1ec8ad 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -86,6 +86,7 @@ int main(int argc, const char* argv[]) { QCommandLineOption responseTokensOption("tokens", "set response tokens ", "json"); QCommandLineOption displayNameOption("displayName", "set user display name ", "string"); QCommandLineOption setBookmarkOption("setBookmark", "set bookmark key=value pair", "string"); + QCommandLineOption defaultScriptOverrideOption("defaultScriptsOverride", "override defaultsScripts.js", "string"); parser.addOption(urlOption); parser.addOption(noLauncherOption); @@ -99,6 +100,7 @@ int main(int argc, const char* argv[]) { parser.addOption(responseTokensOption); parser.addOption(displayNameOption); parser.addOption(setBookmarkOption); + parser.addOption(defaultScriptOverrideOption); if (!parser.parse(arguments)) { std::cout << parser.errorText().toStdString() << std::endl; // Avoid Qt log spam diff --git a/interface/src/octree/OctreePacketProcessor.cpp b/interface/src/octree/OctreePacketProcessor.cpp index 6b07e6717c..c6f908e039 100644 --- a/interface/src/octree/OctreePacketProcessor.cpp +++ b/interface/src/octree/OctreePacketProcessor.cpp @@ -63,7 +63,6 @@ void OctreePacketProcessor::processPacket(QSharedPointer messag // construct a new packet from the piggybacked one auto buffer = std::unique_ptr(new char[piggybackBytes]); memcpy(buffer.get(), message->getRawMessage() + statsMessageLength, piggybackBytes); - auto newPacket = NLPacket::fromReceivedPacket(std::move(buffer), piggybackBytes, message->getSenderSockAddr()); message = QSharedPointer::create(*newPacket); } else { @@ -80,7 +79,6 @@ void OctreePacketProcessor::processPacket(QSharedPointer messag const QUuid& senderUUID = sendingNode->getUUID(); if (!versionDebugSuppressMap.contains(senderUUID, packetType)) { - qDebug() << "Was stats packet? " << wasStatsPacket; qDebug() << "OctreePacketProcessor - piggyback packet version mismatch on" << packetType << "- Sender" << senderUUID << "sent" << (int) message->getVersion() << "but" @@ -115,7 +113,9 @@ void OctreePacketProcessor::processPacket(QSharedPointer messag auto renderer = qApp->getEntities(); if (renderer) { renderer->processDatagram(*message, sendingNode); - _safeLanding->noteReceivedsequenceNumber(renderer->getLastOctreeMessageSequence()); + if (_safeLanding && _safeLanding->isTracking()) { + _safeLanding->addToSequence(renderer->getLastOctreeMessageSequence()); + } } } } break; @@ -124,7 +124,9 @@ void OctreePacketProcessor::processPacket(QSharedPointer messag // Read sequence # OCTREE_PACKET_SEQUENCE completionNumber; message->readPrimitive(&completionNumber); - _safeLanding->setCompletionSequenceNumbers(0, completionNumber); + if (_safeLanding) { + _safeLanding->finishSequence(0, completionNumber); + } } break; default: { @@ -133,6 +135,31 @@ void OctreePacketProcessor::processPacket(QSharedPointer messag } } -void OctreePacketProcessor::startEntitySequence() { - _safeLanding->startEntitySequence(qApp->getEntities()); +void OctreePacketProcessor::startSafeLanding() { + if (_safeLanding) { + _safeLanding->startTracking(qApp->getEntities()); + } +} + +void OctreePacketProcessor::updateSafeLanding() { + if (_safeLanding) { + _safeLanding->updateTracking(); + } +} + +void OctreePacketProcessor::stopSafeLanding() { + if (_safeLanding) { + _safeLanding->stopTracking(); + } +} + +bool OctreePacketProcessor::safeLandingIsActive() const { + return _safeLanding && _safeLanding->isTracking(); +} + +bool OctreePacketProcessor::safeLandingIsComplete() const { + if (_safeLanding) { + return _safeLanding->trackingIsComplete(); + } + return false; } diff --git a/interface/src/octree/OctreePacketProcessor.h b/interface/src/octree/OctreePacketProcessor.h index d6ffb942e6..eacc15f62d 100644 --- a/interface/src/octree/OctreePacketProcessor.h +++ b/interface/src/octree/OctreePacketProcessor.h @@ -25,8 +25,12 @@ public: OctreePacketProcessor(); ~OctreePacketProcessor(); - void startEntitySequence(); - bool isLoadSequenceComplete() const { return _safeLanding->isLoadSequenceComplete(); } + void startSafeLanding(); + void updateSafeLanding(); + void stopSafeLanding(); + bool safeLandingIsActive() const; + bool safeLandingIsComplete() const; + float domainLoadingProgress() const { return _safeLanding->loadingProgressPercentage(); } signals: diff --git a/interface/src/octree/SafeLanding.cpp b/interface/src/octree/SafeLanding.cpp index 2e11de508b..75e512232b 100644 --- a/interface/src/octree/SafeLanding.cpp +++ b/interface/src/octree/SafeLanding.cpp @@ -19,6 +19,11 @@ const int SafeLanding::SEQUENCE_MODULO = std::numeric_limits::max() + 1; +CalculateEntityLoadingPriority SafeLanding::entityLoadingOperatorElevateCollidables = [](const EntityItem& entityItem) { + const int COLLIDABLE_ENTITY_PRIORITY = 10.0f; + return entityItem.getCollisionless() * COLLIDABLE_ENTITY_PRIORITY; +}; + namespace { template bool lessThanWraparound(int a, int b) { constexpr int MAX_T_VALUE = std::numeric_limits::max(); @@ -33,61 +38,46 @@ bool SafeLanding::SequenceLessThan::operator()(const int& a, const int& b) const return lessThanWraparound(a, b); } -void SafeLanding::startEntitySequence(QSharedPointer entityTreeRenderer) { - +void SafeLanding::startTracking(QSharedPointer entityTreeRenderer) { if (!entityTreeRenderer.isNull()) { auto entityTree = entityTreeRenderer->getTree(); - if (entityTree) { + if (entityTree && !_trackingEntities) { Locker lock(_lock); _entityTreeRenderer = entityTreeRenderer; _trackedEntities.clear(); - _trackingEntities = true; _maxTrackedEntityCount = 0; + _initialStart = INVALID_SEQUENCE; + _initialEnd = INVALID_SEQUENCE; + _sequenceNumbers.clear(); + _trackingEntities = true; + _startTime = usecTimestampNow(); + connect(std::const_pointer_cast(entityTree).get(), &EntityTree::addingEntity, this, &SafeLanding::addTrackedEntity, Qt::DirectConnection); connect(std::const_pointer_cast(entityTree).get(), &EntityTree::deletingEntity, this, &SafeLanding::deleteTrackedEntity); - _sequenceNumbers.clear(); - _initialStart = INVALID_SEQUENCE; - _initialEnd = INVALID_SEQUENCE; - _startTime = usecTimestampNow(); - EntityTreeRenderer::setEntityLoadingPriorityFunction(&ElevatedPriority); + _prevEntityLoadingPriorityOperator = EntityTreeRenderer::getEntityLoadingPriorityOperator(); + EntityTreeRenderer::setEntityLoadingPriorityFunction(entityLoadingOperatorElevateCollidables); } } } -void SafeLanding::stopEntitySequence() { - Locker lock(_lock); - _trackingEntities = false; - _maxTrackedEntityCount = 0; - _trackedEntityStabilityCount = 0; - _initialStart = INVALID_SEQUENCE; - _initialEnd = INVALID_SEQUENCE; - _trackedEntities.clear(); - _sequenceNumbers.clear(); -} - void SafeLanding::addTrackedEntity(const EntityItemID& entityID) { - if (_trackingEntities) { + if (_trackingEntities && _entityTreeRenderer) { Locker lock(_lock); + auto entityTree = _entityTreeRenderer->getTree(); + if (entityTree) { + EntityItemPointer entity = entityTree->findEntityByID(entityID); + if (entity && !entity->isLocalEntity() && entity->getCreated() < _startTime) { + _trackedEntities.emplace(entityID, entity); - if (_entityTreeRenderer.isNull() || _entityTreeRenderer->getTree() == nullptr) { - return; - } - - EntityItemPointer entity = _entityTreeRenderer->getTree()->findEntityByID(entityID); - - if (entity && !entity->isLocalEntity() && entity->getCreated() < _startTime) { - - _trackedEntities.emplace(entityID, entity); - int trackedEntityCount = (int)_trackedEntities.size(); - - if (trackedEntityCount > _maxTrackedEntityCount) { - _maxTrackedEntityCount = trackedEntityCount; - _trackedEntityStabilityCount = 0; + int trackedEntityCount = (int)_trackedEntities.size(); + if (trackedEntityCount > _maxTrackedEntityCount) { + _maxTrackedEntityCount = trackedEntityCount; + _trackedEntityStabilityCount = 0; + } } - //qCDebug(interfaceapp) << "Safe Landing: Tracking entity " << entity->getItemName(); } } } @@ -97,32 +87,92 @@ void SafeLanding::deleteTrackedEntity(const EntityItemID& entityID) { _trackedEntities.erase(entityID); } -void SafeLanding::setCompletionSequenceNumbers(int first, int last) { +void SafeLanding::finishSequence(int first, int last) { Locker lock(_lock); - if (_initialStart == INVALID_SEQUENCE) { + if (_trackingEntities) { _initialStart = first; _initialEnd = last; } } -void SafeLanding::noteReceivedsequenceNumber(int sequenceNumber) { - if (_trackingEntities) { +void SafeLanding::addToSequence(int sequenceNumber) { + Locker lock(_lock); + _sequenceNumbers.insert(sequenceNumber); +} + +void SafeLanding::updateTracking() { + if (!_trackingEntities || !_entityTreeRenderer) { + return; + } + + { Locker lock(_lock); - _sequenceNumbers.insert(sequenceNumber); + bool enableInterstitial = DependencyManager::get()->getDomainHandler().getInterstitialModeEnabled(); + auto entityMapIter = _trackedEntities.begin(); + while (entityMapIter != _trackedEntities.end()) { + auto entity = entityMapIter->second; + bool isVisuallyReady = true; + if (enableInterstitial) { + auto entityRenderable = _entityTreeRenderer->renderableForEntityId(entityMapIter->first); + if (!entityRenderable) { + _entityTreeRenderer->addingEntity(entityMapIter->first); + } + isVisuallyReady = entity->isVisuallyReady() || (!entityRenderable && !entity->isParentPathComplete()); + } + if (isEntityPhysicsReady(entity) && isVisuallyReady) { + entityMapIter = _trackedEntities.erase(entityMapIter); + } else { + if (!isVisuallyReady) { + entity->requestRenderUpdate(); + } + entityMapIter++; + } + } + if (enableInterstitial) { + _trackedEntityStabilityCount++; + } + } + + if (_trackedEntities.empty()) { + // no more tracked entities --> check sequenceNumbers + if (_initialStart != INVALID_SEQUENCE) { + bool shouldStop = false; + { + Locker lock(_lock); + int sequenceSize = _initialStart <= _initialEnd ? _initialEnd - _initialStart: + _initialEnd + SEQUENCE_MODULO - _initialStart; + auto startIter = _sequenceNumbers.find(_initialStart); + auto endIter = _sequenceNumbers.find(_initialEnd - 1); + + bool missingSequenceNumbers = qApp->isMissingSequenceNumbers(); + shouldStop = (sequenceSize == 0 || + (startIter != _sequenceNumbers.end() && + endIter != _sequenceNumbers.end() && + ((distance(startIter, endIter) == sequenceSize - 1) || !missingSequenceNumbers))); + } + if (shouldStop) { + stopTracking(); + } + } } } -bool SafeLanding::isLoadSequenceComplete() { - if ((isEntityLoadingComplete() && isSequenceNumbersComplete()) || qApp->failedToConnectToEntityServer()) { - Locker lock(_lock); - _initialStart = INVALID_SEQUENCE; - _initialEnd = INVALID_SEQUENCE; - _entityTreeRenderer.clear(); - _trackingEntities = false; // Don't track anything else that comes in. - EntityTreeRenderer::setEntityLoadingPriorityFunction(StandardPriority); +void SafeLanding::stopTracking() { + Locker lock(_lock); + _trackingEntities = false; + if (_entityTreeRenderer) { + auto entityTree = _entityTreeRenderer->getTree(); + disconnect(std::const_pointer_cast(entityTree).get(), + &EntityTree::addingEntity, this, &SafeLanding::addTrackedEntity); + disconnect(std::const_pointer_cast(entityTree).get(), + &EntityTree::deletingEntity, this, &SafeLanding::deleteTrackedEntity); + _entityTreeRenderer.reset(); } + EntityTreeRenderer::setEntityLoadingPriorityFunction(_prevEntityLoadingPriorityOperator); +} - return !_trackingEntities; +bool SafeLanding::trackingIsComplete() const { + return !_trackingEntities && (_initialStart != INVALID_SEQUENCE); } float SafeLanding::loadingProgressPercentage() { @@ -141,29 +191,6 @@ float SafeLanding::loadingProgressPercentage() { return entityReadyPercentage; } -bool SafeLanding::isSequenceNumbersComplete() { - if (_initialStart != INVALID_SEQUENCE) { - Locker lock(_lock); - int sequenceSize = _initialStart <= _initialEnd ? _initialEnd - _initialStart: - _initialEnd + SEQUENCE_MODULO - _initialStart; - auto startIter = _sequenceNumbers.find(_initialStart); - auto endIter = _sequenceNumbers.find(_initialEnd - 1); - - bool missingSequenceNumbers = qApp->isMissingSequenceNumbers(); - if (sequenceSize == 0 || - (startIter != _sequenceNumbers.end() - && endIter != _sequenceNumbers.end() - && ((distance(startIter, endIter) == sequenceSize - 1) || !missingSequenceNumbers))) { - bool enableInterstitial = DependencyManager::get()->getDomainHandler().getInterstitialModeEnabled(); - if (!enableInterstitial) { - _trackingEntities = false; // Don't track anything else that comes in. - } - return true; - } - } - return false; -} - bool SafeLanding::isEntityPhysicsReady(const EntityItemPointer& entity) { if (entity && !entity->getCollisionless()) { const auto& entityType = entity->getType(); @@ -181,56 +208,9 @@ bool SafeLanding::isEntityPhysicsReady(const EntityItemPointer& entity) { } } } - return true; } -bool SafeLanding::isEntityLoadingComplete() { - Locker lock(_lock); - - - auto entityTree = qApp->getEntities(); - auto entityMapIter = _trackedEntities.begin(); - - bool enableInterstitial = DependencyManager::get()->getDomainHandler().getInterstitialModeEnabled(); - - while (entityMapIter != _trackedEntities.end()) { - auto entity = entityMapIter->second; - - bool isVisuallyReady = true; - - if (enableInterstitial) { - auto entityRenderable = entityTree->renderableForEntityId(entityMapIter->first); - if (!entityRenderable) { - entityTree->addingEntity(entityMapIter->first); - } - - isVisuallyReady = entity->isVisuallyReady() || (!entityRenderable && !entity->isParentPathComplete()); - } - - if (isEntityPhysicsReady(entity) && isVisuallyReady) { - entityMapIter = _trackedEntities.erase(entityMapIter); - } else { - if (!isVisuallyReady) { - entity->requestRenderUpdate(); - } - - entityMapIter++; - } - } - - if (enableInterstitial) { - _trackedEntityStabilityCount++; - } - - - return _trackedEntities.empty(); -} - -float SafeLanding::ElevatedPriority(const EntityItem& entityItem) { - return entityItem.getCollisionless() ? 0.0f : 10.0f; -} - void SafeLanding::debugDumpSequenceIDs() const { int p = -1; qCDebug(interfaceapp) << "Sequence set size:" << _sequenceNumbers.size(); diff --git a/interface/src/octree/SafeLanding.h b/interface/src/octree/SafeLanding.h index 428ca15bdc..87dac16ba3 100644 --- a/interface/src/octree/SafeLanding.h +++ b/interface/src/octree/SafeLanding.h @@ -20,16 +20,21 @@ #include "EntityItem.h" #include "EntityDynamicInterface.h" +#include "EntityTreeRenderer.h" + class EntityTreeRenderer; class EntityItemID; class SafeLanding : public QObject { public: - void startEntitySequence(QSharedPointer entityTreeRenderer); - void stopEntitySequence(); - void setCompletionSequenceNumbers(int first, int last); // 'last' exclusive. - void noteReceivedsequenceNumber(int sequenceNumber); - bool isLoadSequenceComplete(); + void startTracking(QSharedPointer entityTreeRenderer); + void updateTracking(); + void stopTracking(); + bool isTracking() const { return _trackingEntities; } + bool trackingIsComplete() const; + + void finishSequence(int first, int last); // 'last' exclusive. + void addToSequence(int sequenceNumber); float loadingProgressPercentage(); private slots: @@ -37,10 +42,8 @@ private slots: void deleteTrackedEntity(const EntityItemID& entityID); private: - bool isSequenceNumbersComplete(); bool isEntityPhysicsReady(const EntityItemPointer& entity); void debugDumpSequenceIDs() const; - bool isEntityLoadingComplete(); std::mutex _lock; using Locker = std::lock_guard; @@ -63,8 +66,8 @@ private: std::set _sequenceNumbers; - static float ElevatedPriority(const EntityItem& entityItem); - static float StandardPriority(const EntityItem&) { return 0.0f; } + static CalculateEntityLoadingPriority entityLoadingOperatorElevateCollidables; + CalculateEntityLoadingPriority _prevEntityLoadingPriorityOperator { nullptr }; static const int SEQUENCE_MODULO; }; diff --git a/interface/src/raypick/LaserPointerScriptingInterface.h b/interface/src/raypick/LaserPointerScriptingInterface.h index 425ffd7de4..6c5ce0dbaf 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.h +++ b/interface/src/raypick/LaserPointerScriptingInterface.h @@ -21,121 +21,146 @@ class LaserPointerScriptingInterface : public QObject, public Dependency { SINGLETON_DEPENDENCY /**jsdoc - * Synonym for {@link Pointers} as used for laser pointers. Deprecated. + * The LaserPointers API is a subset of the {@link Pointers} API. It lets you create, manage, and visually + * represent objects for repeatedly calculating ray intersections with avatars, entities, and overlays. Ray pointers can also + * be configured to generate events on entities and overlays intersected. + * + *

Deprecated: This API is deprecated. Use {@link Pointers} instead. * * @namespace LaserPointers * * @hifi-interface * @hifi-client-entity * @hifi-avatar + * + * @borrows Pointers.enablePointer as enableLaserPointer + * @borrows Pointers.disablePointer as disableLaserPointer + * @borrows Pointers.removePointer as removeLaserPointer + * @borrows Pointers.setPrecisionPicking as setPrecisionPicking */ public: /**jsdoc + * Creates a new ray pointer. The pointer can have a wide range of behaviors depending on the properties specified. For + * example, it may be a static ray pointer, a mouse ray pointer, or joint ray pointer. + *

Warning: Pointers created using this method currently always intersect at least visible and + * collidable things but this may not always be the case.

* @function LaserPointers.createLaserPointer - * @param {Pointers.LaserPointerProperties} properties - * @returns {number} + * @param {Pointers.RayPointerProperties} properties - The properties of the pointer, including the properties of the + * underlying pick that the pointer uses to do its picking. + * @returns {number} The ID of the pointer if successfully created, otherwise 0. */ Q_INVOKABLE unsigned int createLaserPointer(const QVariant& properties) const; - /**jsdoc - * @function LaserPointers.enableLaserPointer - * @param {number} id - */ + // jsdoc @borrows from Pointers Q_INVOKABLE void enableLaserPointer(unsigned int uid) const { DependencyManager::get()->enablePointer(uid); } - /**jsdoc - * @function LaserPointers.disableLaserPointer - * @param {number} id - */ + // jsdoc @borrows from Pointers Q_INVOKABLE void disableLaserPointer(unsigned int uid) const { DependencyManager::get()->disablePointer(uid); } - /**jsdoc - * @function LaserPointers.removeLaserPointer - * @param {number} id - */ + // jsdoc @borrows from Pointers Q_INVOKABLE void removeLaserPointer(unsigned int uid) const { DependencyManager::get()->removePointer(uid); } /**jsdoc + * Edits a render state of a pointer, to change its visual appearance for the state when the pointer is intersecting + * something. + *

Note: You can only edit the properties of the existing parts of the pointer; you cannot change the + * type of any part.

+ *

Note: You cannot use this method to change the appearance of a default render state.

* @function LaserPointers.editRenderState - * @param {number} id - * @param {string} renderState - * @param {Pointers.RayPointerRenderState} properties + * @param {number} id - The ID of the pointer. + * @param {string} renderState - The name of the render state to edit. + * @param {Pointers.RayPointerRenderState} properties - The new properties for the render state. Only the overlay + * properties to change need be specified. */ Q_INVOKABLE void editRenderState(unsigned int uid, const QString& renderState, const QVariant& properties) const; /**jsdoc + * Sets the render state of a pointer, to change its visual appearance and possibly disable or enable it. * @function LaserPointers.setRenderState - * @param {string} renderState - * @param {number} id + * @param {string} renderState -

The name of the render state to set the pointer to. This may be:

+ *
    + *
  • The name of one of the render states set in the pointer's properties.
  • + *
  • "", to hide the pointer and disable emitting of events.
  • + *
+ * @param {number} id - The ID of the pointer. */ Q_INVOKABLE void setRenderState(unsigned int uid, const QString& renderState) const { DependencyManager::get()->setRenderState(uid, renderState.toStdString()); } /**jsdoc + * Gets the most recent intersection of a pointer. A pointer continues to be updated ready to return a result, as long as + * it is enabled, regardless of the render state. * @function LaserPointers.getPrevRayPickResult - * @param {number} id - * @returns {RayPickResult} + * @param {number} id - The ID of the pointer. + * @returns {RayPickResult} The most recent intersection of the pointer. */ Q_INVOKABLE QVariantMap getPrevRayPickResult(unsigned int uid) const; - - /**jsdoc - * @function LaserPointers.setPrecisionPicking - * @param {number} id - * @param {boolean} precisionPicking - */ + // jsdoc @borrows from Pointers Q_INVOKABLE void setPrecisionPicking(unsigned int uid, bool precisionPicking) const { DependencyManager::get()->setPrecisionPicking(uid, precisionPicking); } /**jsdoc + * Sets the length of a pointer. * @function LaserPointers.setLaserLength - * @param {number} id - * @param {number} laserLength + * @param {number} id - The ID of the pointer. + * @param {number} laserLength - The desired length of the pointer. */ Q_INVOKABLE void setLaserLength(unsigned int uid, float laserLength) const { DependencyManager::get()->setLength(uid, laserLength); } /**jsdoc + * Sets a list of entity and avatar IDs that a pointer should ignore during intersection. * @function LaserPointers.setIgnoreItems - * @param {number} id - * @param {Uuid[]} ignoreItems + * @param {number} id - The ID of the pointer. + * @param {Uuid[]} ignoreItems - A list of IDs to ignore. */ Q_INVOKABLE void setIgnoreItems(unsigned int uid, const QScriptValue& ignoreEntities) const; /**jsdoc + * Sets a list of entity and avatar IDs that a pointer should include during intersection, instead of intersecting with + * everything. * @function LaserPointers.setIncludeItems - * @param {number} id - * @param {Uuid[]} includeItems + * @param {number} id - The ID of the pointer. + * @param {Uuid[]} includeItems - A list of IDs to include. */ Q_INVOKABLE void setIncludeItems(unsigned int uid, const QScriptValue& includeEntities) const; /**jsdoc + * Locks a pointer onto a specific entity or avatar. * @function LaserPointers.setLockEndUUID - * @param {number} id - * @param {Uuid} itemID - * @param {boolean} isAvatar - * @param {Mat4} [offsetMat] + * @param {number} id - The ID of the pointer. + * @param {Uuid} targetID - The ID of the entity or avatar to lock the pointer on to. + * @param {boolean} isAvatar - true if the target is an avatar, false if it is an entity. + * @param {Mat4} [offset] - The offset of the target point from the center of the target item. If not specified, the + * pointer locks on to the center of the target item. */ Q_INVOKABLE void setLockEndUUID(unsigned int uid, const QUuid& objectID, bool isAvatar, const glm::mat4& offsetMat = glm::mat4()) const { DependencyManager::get()->setLockEndUUID(uid, objectID, isAvatar, offsetMat); } /**jsdoc + * Checks if a pointer is associated with the left hand: a pointer with joint property set to + * "_CONTROLLER_LEFTHAND" or "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND". * @function LaserPointers.isLeftHand - * @param {number} id - * @returns {boolean} + * @param {number} id - The ID of the pointer. + * @returns {boolean} true if the pointer is associated with the left hand, false if it isn't. */ Q_INVOKABLE bool isLeftHand(unsigned int uid) { return DependencyManager::get()->isLeftHand(uid); } /**jsdoc + * Checks if a pointer is associated with the right hand: a pointer with joint property set to + * "_CONTROLLER_RIGHTHAND" or "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND". * @function LaserPointers.isRightHand - * @param {number} id - * @returns {boolean} + * @param {number} id - The ID of the pointer. + * @returns {boolean} true if the pointer is associated with the right hand, false if it isn't. */ Q_INVOKABLE bool isRightHand(unsigned int uid) { return DependencyManager::get()->isRightHand(uid); } /**jsdoc + * Checks if a pointer is associated with the system mouse: a pointer with joint property set to + * "Mouse". * @function LaserPointers.isMouse - * @param {number} id - * @returns {boolean} + * @param {number} id - The ID of the pointer. + * @returns {boolean} true if the pointer is associated with the system mouse, false if it isn't. */ Q_INVOKABLE bool isMouse(unsigned int uid) { return DependencyManager::get()->isMouse(uid); } }; diff --git a/interface/src/raypick/ParabolaPointer.cpp b/interface/src/raypick/ParabolaPointer.cpp index 23fc1cb4bd..0589124db8 100644 --- a/interface/src/raypick/ParabolaPointer.cpp +++ b/interface/src/raypick/ParabolaPointer.cpp @@ -405,7 +405,8 @@ gpu::PipelinePointer ParabolaPointer::RenderState::ParabolaRenderItem::getParabo using namespace shader::render_utils::program; static const std::vector> keys = { - std::make_tuple(false, false, parabola), std::make_tuple(false, true, forward_parabola), std::make_tuple(true, false, parabola_translucent)/*, std::make_tuple(true, true, forward_parabola_translucent)*/ + std::make_tuple(false, false, parabola), std::make_tuple(false, true, parabola_forward), + std::make_tuple(true, false, parabola_translucent), std::make_tuple(true, true, parabola_forward) // The forward opaque/translucent pipelines are the same for now }; for (auto& key : keys) { @@ -423,9 +424,6 @@ gpu::PipelinePointer ParabolaPointer::RenderState::ParabolaRenderItem::getParabo _parabolaPipelines[{std::get<0>(key), std::get<1>(key)}] = gpu::Pipeline::create(gpu::Shader::createProgram(std::get<2>(key)), state); } - - // The forward opaque/translucent pipelines are the same for now - _parabolaPipelines[{ true, true }] = _parabolaPipelines[{ false, true}]; } return _parabolaPipelines[{ _parabolaData.color.a < 1.0f, forward }]; } diff --git a/interface/src/raypick/PickScriptingInterface.cpp b/interface/src/raypick/PickScriptingInterface.cpp index 82d00d803f..12f68c1430 100644 --- a/interface/src/raypick/PickScriptingInterface.cpp +++ b/interface/src/raypick/PickScriptingInterface.cpp @@ -55,7 +55,7 @@ PickFilter getPickFilter(unsigned int filter) { } /**jsdoc - * A set of properties that can be passed to {@link Picks.createPick} when creating a new ray pick. + * The properties of a ray pick. * * @typedef {object} Picks.RayPickProperties * @property {boolean} [enabled=false] - true if this pick should start enabled, false if it should @@ -138,7 +138,7 @@ unsigned int PickScriptingInterface::createRayPick(const QVariant& properties) { } /**jsdoc - * A set of properties that can be passed to {@link Picks.createPick} when creating a new stylus pick. + * The properties of a stylus pick. * * @typedef {object} Picks.StylusPickProperties * @property {number} [hand=-1] 0 for the left hand, 1 for the right hand, invalid (-1) @@ -189,7 +189,7 @@ unsigned int PickScriptingInterface::createStylusPick(const QVariant& properties // NOTE: Laser pointer still uses scaleWithAvatar. Until scaleWithAvatar is also deprecated for pointers, scaleWithAvatar should not be removed from the pick API. /**jsdoc - * A set of properties that can be passed to {@link Picks.createPick} when creating a new parabola pick. + * The properties of a parabola pick. * * @typedef {object} Picks.ParabolaPickProperties * @property {boolean} [enabled=false] - true if this pick should start enabled, false if it should @@ -297,7 +297,7 @@ unsigned int PickScriptingInterface::createParabolaPick(const QVariant& properti /**jsdoc - * A set of properties that can be passed to {@link Picks.createPick} when creating a new collision pick. + * The properties of a collision pick. * * @typedef {object} Picks.CollisionPickProperties * @property {boolean} [enabled=false] - true if this pick should start enabled, false if it should diff --git a/interface/src/raypick/PickScriptingInterface.h b/interface/src/raypick/PickScriptingInterface.h index 1cbdaa92f7..e973ee3643 100644 --- a/interface/src/raypick/PickScriptingInterface.h +++ b/interface/src/raypick/PickScriptingInterface.h @@ -194,7 +194,8 @@ public: Q_INVOKABLE QVariantMap getPrevPickResult(unsigned int uid); /**jsdoc - * Sets whether or not to use precision picking, i.e., whether to pick against precise meshes or coarse meshes. + * Sets whether or not a pick should use precision picking, i.e., whether it should pick against precise meshes or coarse + * meshes. * This has the same effect as using the PICK_PRECISE or PICK_COARSE filter flags. * @function Picks.setPrecisionPicking * @param {number} id - The ID of the pick. @@ -203,7 +204,7 @@ public: Q_INVOKABLE void setPrecisionPicking(unsigned int uid, bool precisionPicking); /**jsdoc - * Sets a list of entity and avatar IDs to ignore during intersection. + * Sets a list of entity and avatar IDs that a pick should ignore during intersection. *

Note: Not used by stylus picks.

* @function Picks.setIgnoreItems * @param {number} id - The ID of the pick. @@ -212,8 +213,9 @@ public: Q_INVOKABLE void setIgnoreItems(unsigned int uid, const QScriptValue& ignoreItems); /**jsdoc - * Sets a list of entity IDs and/or avatar IDs to include during intersection, instead of intersecting with everything. - *

Note: Stylus picks only intersect with objects in their include list.

+ * Sets a list of entity and avatar IDs that a pick should include during intersection, instead of intersecting with + * everything. + *

Note: Stylus picks only intersect with items in their include list.

* @function Picks.setIncludeItems * @param {number} id - The ID of the pick. * @param {Uuid[]} includeItems - The list of IDs to include. @@ -221,9 +223,9 @@ public: Q_INVOKABLE void setIncludeItems(unsigned int uid, const QScriptValue& includeItems); /**jsdoc - * Checks if a pick is associated with the left hand: a ray or parabola pick with joint set to - * "_CONTROLLER_LEFTHAND" or "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", or a stylus pick with hand - * set to 0. + * Checks if a pick is associated with the left hand: a ray or parabola pick with joint property set to + * "_CONTROLLER_LEFTHAND" or "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", or a stylus pick with + * hand property set to 0. * @function Picks.isLeftHand * @param {number} id - The ID of the pick. * @returns {boolean} true if the pick is associated with the left hand, false if it isn't. @@ -231,9 +233,9 @@ public: Q_INVOKABLE bool isLeftHand(unsigned int uid); /**jsdoc - * Checks if a pick is associated with the right hand: a ray or parabola pick with joint set to - * "_CONTROLLER_RIGHTHAND" or "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND", or a stylus pick with hand - * set to 1. + * Checks if a pick is associated with the right hand: a ray or parabola pick with joint property set to + * "_CONTROLLER_RIGHTHAND" or "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND", or a stylus pick with + * hand property set to 1. * @function Picks.isRightHand * @param {number} id - The ID of the pick. * @returns {boolean} true if the pick is associated with the right hand, false if it isn't. @@ -241,7 +243,8 @@ public: Q_INVOKABLE bool isRightHand(unsigned int uid); /**jsdoc - * Checks if a pick is associated with the system mouse: a ray or parabola pick with joint set to "Mouse". + * Checks if a pick is associated with the system mouse: a ray or parabola pick with joint property set to + * "Mouse". * @function Picks.isMouse * @param {number} id - The ID of the pick. * @returns {boolean} true if the pick is associated with the system mouse, false if it isn't. diff --git a/interface/src/raypick/PointerScriptingInterface.cpp b/interface/src/raypick/PointerScriptingInterface.cpp index 1c80caff88..f1dcf7bd5d 100644 --- a/interface/src/raypick/PointerScriptingInterface.cpp +++ b/interface/src/raypick/PointerScriptingInterface.cpp @@ -51,21 +51,22 @@ unsigned int PointerScriptingInterface::createPointer(const PickQuery::PickType& } /**jsdoc - * A set of properties that can be passed to {@link Pointers.createPointer} to create a new Pointer. Contains the relevant {@link Picks.PickProperties} to define the underlying Pick. + * The properties of a stylus pointer. These include the properties from the underlying stylus pick that the pointer uses. * @typedef {object} Pointers.StylusPointerProperties - * @property {boolean} [hover=false] If this pointer should generate hover events. - * @property {boolean} [enabled=false] - * @property {Vec3} [tipOffset] The specified offset of the from the joint index. - * @property {Pointers.StylusPointerProperties.model} [model] Data to replace the default model url, positionOffset and rotationOffset. + * @property {Pointers.StylusPointerModel} [model] - Override some or all of the default stylus model properties. + * @property {boolean} [hover=false] - true if the pointer generates {@link Entities} hover events, + * false if it doesn't. + * @see {@link Picks.StylusPickProperties} for additional properties from the underlying stylus pick. + */ +/**jsdoc + * The properties of a stylus pointer model. + * @typedef {object} Pointers.StylusPointerModel + * @property {string} [url] - The url of a model to use for the stylus, to override the default stylus mode. + * @property {Vec3} [dimensions] - The dimensions of the stylus, to override the default stylus dimensions. + * @property {Vec3} [positionOffset] - The position offset of the model from the stylus tip, to override the default position + * offset. + * @property {Quat} [rotationOffset] - The rotation offset of the model from the hand, to override the default rotation offset. */ - /**jsdoc - * properties defining stylus pick model that can be included to {@link Pointers.StylusPointerProperties} - * @typedef {object} Pointers.StylusPointerProperties.model - * @property {string} [url] url to the model - * @property {Vec3} [dimensions] the dimensions of the model - * @property {Vec3} [positionOffset] the position offset of the model from the stylus tip. - * @property {Vec3} [rotationOffset] the rotation offset of the model from the parent joint index - */ unsigned int PointerScriptingInterface::createStylus(const QVariant& properties) const { QVariantMap propertyMap = properties.toMap(); @@ -104,48 +105,76 @@ unsigned int PointerScriptingInterface::createStylus(const QVariant& properties) } /**jsdoc - * A set of properties used to define the visual aspect of a Ray Pointer in the case that the Pointer is not intersecting something. Same as a {@link Pointers.RayPointerRenderState}, - * but with an additional distance field. - * + * Properties that define the visual appearance of a ray pointer when the pointer is not intersecting something. These are the + * properties of {@link Pointers.RayPointerRenderState} but with an additional property. * @typedef {object} Pointers.DefaultRayPointerRenderState - * @augments Pointers.RayPointerRenderState - * @property {number} distance The distance at which to render the end of this Ray Pointer, if one is defined. + * @property {number} distance - The distance at which to render the end of the ray pointer. + * @see {@link Pointers.RayPointerRenderState} for the remainder of the properties. */ /**jsdoc - * A set of properties which define the visual aspect of a Ray Pointer in the case that the Pointer is intersecting something. - * + * Properties that define the visual appearance of a ray pointer when the pointer is intersecting something. * @typedef {object} Pointers.RayPointerRenderState - * @property {string} name When using {@link Pointers.createPointer}, the name of this render state, used by {@link Pointers.setRenderState} and {@link Pointers.editRenderState} - * @property {Overlays.OverlayProperties|QUuid} [start] When using {@link Pointers.createPointer}, an optionally defined object to represent the beginning of the Ray Pointer, - * using the properties you would normally pass to {@link Overlays.addOverlay}, plus the type (as a type field). - * When returned from {@link Pointers.getPointerProperties}, the ID of the created object if it exists, or a null ID otherwise. - * @property {Overlays.OverlayProperties|QUuid} [path] When using {@link Pointers.createPointer}, an optionally defined object to represent the path of the Ray Pointer, - * using the properties you would normally pass to {@link Overlays.addOverlay}, plus the type (as a type field), which must be "line3d". - * When returned from {@link Pointers.getPointerProperties}, the ID of the created object if it exists, or a null ID otherwise. - * @property {Overlays.OverlayProperties|QUuid} [end] When using {@link Pointers.createPointer}, an optionally defined object to represent the end of the Ray Pointer, - * using the properties you would normally pass to {@link Overlays.addOverlay}, plus the type (as a type field). - * When returned from {@link Pointers.getPointerProperties}, the ID of the created object if it exists, or a null ID otherwise. + * @property {string} name - When creating using {@link Pointers.createPointer}, the name of the render state. + * @property {Overlays.OverlayProperties|Uuid} [start] + *

When creating or editing using {@link Pointers.createPointer} or {@link Pointers.editRenderState}, the properties of + * an overlay to render at the start of the ray pointer. The type property must be specified.

+ *

When getting using {@link Pointers.getPointerProperties}, the ID of the overlay rendered at the start of the ray; + * null if there is no overlay. + * + * @property {Overlays.OverlayProperties|Uuid} [path] + *

When creating or editing using {@link Pointers.createPointer} or {@link Pointers.editRenderState}, the properties of + * the overlay rendered for the path of the ray pointer. The type property must be specified and be + * "line3d".

+ *

When getting using {@link Pointers.getPointerProperties}, the ID of the overlay rendered for the path of the ray; + * null if there is no overlay. + * + * @property {Overlays.OverlayProperties|Uuid} [end] + *

When creating or editing using {@link Pointers.createPointer} or {@link Pointers.editRenderState}, the properties of + * an overlay to render at the end of the ray pointer. The type property must be specified.

+ *

When getting using {@link Pointers.getPointerProperties}, the ID of the overlay rendered at the end of the ray; + * null if there is no overlay. */ /**jsdoc - * A set of properties that can be passed to {@link Pointers.createPointer} to create a new Pointer. Contains the relevant {@link Picks.PickProperties} to define the underlying Pick. - * @typedef {object} Pointers.LaserPointerProperties - * @property {boolean} [faceAvatar=false] If true, the end of the Pointer will always rotate to face the avatar. - * @property {boolean} [centerEndY=true] If false, the end of the Pointer will be moved up by half of its height. - * @property {boolean} [lockEnd=false] If true, the end of the Pointer will lock on to the center of the object at which the pointer is pointing. - * @property {boolean} [distanceScaleEnd=false] If true, the dimensions of the end of the Pointer will scale linearly with distance. - * @property {boolean} [scaleWithParent=false] If true, the width of the Pointer's path will scale linearly with the pick parent's scale. scaleWithAvatar is an alias but is deprecated. - * @property {boolean} [followNormal=false] If true, the end of the Pointer will rotate to follow the normal of the intersected surface. - * @property {number} [followNormalStrength=0.0] The strength of the interpolation between the real normal and the visual normal if followNormal is true. 0-1. If 0 or 1, - * the normal will follow exactly. - * @property {boolean} [enabled=false] - * @property {Pointers.RayPointerRenderState[]|Object.} [renderStates] A collection of different visual states to switch between. - * When using {@link Pointers.createPointer}, a list of RayPointerRenderStates. - * When returned from {@link Pointers.getPointerProperties}, a map between render state names and RayPointRenderStates. - * @property {Pointers.DefaultRayPointerRenderState[]|Object.} [defaultRenderStates] A collection of different visual states to use if there is no intersection. - * When using {@link Pointers.createPointer}, a list of DefaultRayPointerRenderStates. - * When returned from {@link Pointers.getPointerProperties}, a map between render state names and DefaultRayPointRenderStates. - * @property {boolean} [hover=false] If this Pointer should generate hover events. - * @property {Pointers.Trigger[]} [triggers] A list of different triggers mechanisms that control this Pointer's click event generation. + * The properties of a ray pointer. These include the properties from the underlying ray pick that the pointer uses. + * @typedef {object} Pointers.RayPointerProperties + * @property {boolean} [faceAvatar=false] - true if the overlay rendered at the end of the ray rotates about the + * world y-axis to always face the avatar; false if it maintains its world orientation. + * @property {boolean} [centerEndY=true] - true if the overlay rendered at the end of the ray is centered on + * the ray end; false if the overlay is positioned against the surface if followNormal is + * true, or above the ray end if followNormal is false. +* @property {boolean} [lockEnd=false] - true if the end of the ray is locked to the center of the object at + * which the ray is pointing; false if the end of the ray is at the intersected surface. + * @property {boolean} [distanceScaleEnd=false] - true if the dimensions of the overlay at the end of the ray + * scale linearly with distance; false if they aren't. + * @property {boolean} [scaleWithParent=false] - true if the width of the ray's path and the size of the + * start and end overlays scale linearly with the pointer parent's scale; false if they don't scale. + * @property {boolean} [scaleWithAvatar=false] - A synonym for scalewithParent. + *

Deprecated: This property is deprecated and will be removed.

+ * @property {boolean} [followNormal=false] - true if the overlay rendered at the end of the ray rotates to + * follow the normal of the surface if one is intersected; false if it doesn't. + * @property {number} [followNormalStrength=0.0] - How quickly the overlay rendered at the end of the ray rotates to follow + * the normal of an intersected surface. If 0 or 1, the overlay rotation follows instantaneously; + * for other values, the larger the value the more quickly the rotation follows. + * @property {Pointers.RayPointerRenderState[]|Object.} [renderStates] + *

A set of visual states that can be switched among using {@link Pointers.setRenderState}. These define the visual + * appearance of the pointer when it is intersecting something.

+ *

When setting using {@link Pointers.createPointer}, an array of + * {@link Pointers.RayPointerRenderState|RayPointerRenderState} values.

+ *

When getting using {@link Pointers.getPointerProperties}, an object mapping render state names to + * {@link Pointers.RayPointerRenderState|RayPointerRenderState} values.

+ * @property {Pointers.DefaultRayPointerRenderState[]|Object.} + * [defaultRenderStates] + *

A set of visual states that can be switched among using {@link Pointers.setRenderState}. These define the visual + * appearance of the pointer when it is not intersecting something.

+ *

When setting using {@link Pointers.createPointer}, an array of + * {@link Pointers.DefaultRayPointerRenderState|DefaultRayPointerRenderState} values.

+ *

When getting using {@link Pointers.getPointerProperties}, an object mapping render state names to + * {@link Pointers.DefaultRayPointerRenderState|DefaultRayPointerRenderState} values.

+ * @property {boolean} [hover=false] - true if the pointer generates {@link Entities} hover events, + * false if it doesn't. + * @property {Pointers.Trigger[]} [triggers=[]] - A list of ways that a {@link Controller} action or function should trigger + * events on the entity or overlay currently intersected. + * @see {@link Picks.RayPickProperties} for additional properties from the underlying ray pick. */ unsigned int PointerScriptingInterface::createLaserPointer(const QVariant& properties) const { QVariantMap propertyMap = properties.toMap(); @@ -260,58 +289,84 @@ unsigned int PointerScriptingInterface::createLaserPointer(const QVariant& prope } /**jsdoc -* The rendering properties of the parabolic path -* -* @typedef {object} Pointers.ParabolaProperties -* @property {Color} color=255,255,255 The color of the parabola. -* @property {number} alpha=1.0 The alpha of the parabola. -* @property {number} width=0.01 The width of the parabola, in meters. -* @property {boolean} isVisibleInSecondaryCamera=false The width of the parabola, in meters. -* @property {boolean} drawInFront=false If true, the parabola is rendered in front of other items in the scene. -*/ + * The visual appearance of the parabolic path. + * @typedef {object} Pointers.ParabolaPointerPath + * @property {Color} [color=255,255,255] - The color of the parabola. + * @property {number} [alpha=1.0] - The opacity of the parabola, range 0.01.0. + * @property {number} [width=0.01] - The width of the parabola, in meters. + * @property {boolean} [isVisibleInSecondaryCamera=false] - true if the parabola is rendered in the secondary + * camera, false if it isn't. + * @property {boolean} [drawInFront=false] - true if the parabola is rendered in front of objects in the world, + * but behind the HUD, false if it is occluded by objects in front of it. + */ /**jsdoc -* A set of properties used to define the visual aspect of a Parabola Pointer in the case that the Pointer is not intersecting something. Same as a {@link Pointers.ParabolaPointerRenderState}, -* but with an additional distance field. -* -* @typedef {object} Pointers.DefaultParabolaPointerRenderState -* @augments Pointers.ParabolaPointerRenderState -* @property {number} distance The distance along the parabola at which to render the end of this Parabola Pointer, if one is defined. -*/ + * Properties that define the visual appearance of a parabola pointer when the pointer is not intersecting something. These are + * properties of {@link Pointers.ParabolaPointerRenderState} but with an additional property. + * @typedef {object} Pointers.DefaultParabolaPointerRenderState + * @property {number} distance - The distance along the parabola at which to render the end of the parabola pointer. + * @see {@link Pointers.ParabolaPointerRenderState} for the remainder of the properties. + */ /**jsdoc -* A set of properties used to define the visual aspect of a Parabola Pointer in the case that the Pointer is intersecting something. -* -* @typedef {object} Pointers.ParabolaPointerRenderState -* @property {string} name When using {@link Pointers.createPointer}, the name of this render state, used by {@link Pointers.setRenderState} and {@link Pointers.editRenderState} -* @property {Overlays.OverlayProperties|QUuid} [start] When using {@link Pointers.createPointer}, an optionally defined object to represent the beginning of the Parabola Pointer, -* using the properties you would normally pass to {@link Overlays.addOverlay}, plus the type (as a type field). -* When returned from {@link Pointers.getPointerProperties}, the ID of the created object if it exists, or a null ID otherwise. -* @property {Pointers.ParabolaProperties} [path] When using {@link Pointers.createPointer}, the optionally defined rendering properties of the parabolic path defined by the Parabola Pointer. -* Not defined in {@link Pointers.getPointerProperties}. -* @property {Overlays.OverlayProperties|QUuid} [end] When using {@link Pointers.createPointer}, an optionally defined object to represent the end of the Parabola Pointer, -* using the properties you would normally pass to {@link Overlays.addOverlay}, plus the type (as a type field). -* When returned from {@link Pointers.getPointerProperties}, the ID of the created object if it exists, or a null ID otherwise. -*/ + * Properties that define the visual appearance of a parabola pointer when the pointer is intersecting something. + * @typedef {object} Pointers.ParabolaPointerRenderState + * @property {string} name - When creating using {@link Pointers.createPointer}, the name of the render state. + * @property {Overlays.OverlayProperties|Uuid} [start] + *

When creating or editing using {@link Pointers.createPointer} or {@link Pointers.editRenderState}, the properties of + * an overlay to render at the start of the parabola pointer. The type property must be specified.

+ *

When getting using {@link Pointers.getPointerProperties}, the ID of the overlay rendered at the start of the + * parabola; null if there is no overlay. + * @property {Pointers.ParabolaPointerPath|Uuid} [path] + *

When creating or editing using {@link Pointers.createPointer} or {@link Pointers.editRenderState}, the properties of + * the rendered path of the parabola pointer.

+ *

This property is not provided when getting using {@link Pointers.getPointerProperties}. + * @property {Overlays.OverlayProperties|Uuid} [end] + *

When creating or editing using {@link Pointers.createPointer} or {@link Pointers.editRenderState}, the properties of + * an overlay to render at the end of the ray pointer. The type property must be specified.

+ *

When getting using {@link Pointers.getPointerProperties}, the ID of the overlay rendered at the end of the parabola; + * null if there is no overlay. + */ /**jsdoc -* A set of properties that can be passed to {@link Pointers.createPointer} to create a new Pointer. Contains the relevant {@link Picks.PickProperties} to define the underlying Pick. -* @typedef {object} Pointers.ParabolaPointerProperties -* @property {boolean} [faceAvatar=false] If true, the end of the Pointer will always rotate to face the avatar. -* @property {boolean} [centerEndY=true] If false, the end of the Pointer will be moved up by half of its height. -* @property {boolean} [lockEnd=false] If true, the end of the Pointer will lock on to the center of the object at which the pointer is pointing. -* @property {boolean} [distanceScaleEnd=false] If true, the dimensions of the end of the Pointer will scale linearly with distance. -* @property {boolean} [scaleWithParent=true] If true, the width of the Pointer's path will scale linearly with the pick parent's scale. scaleWithAvatar is an alias but is deprecated. -* @property {boolean} [followNormal=false] If true, the end of the Pointer will rotate to follow the normal of the intersected surface. -* @property {number} [followNormalStrength=0.0] The strength of the interpolation between the real normal and the visual normal if followNormal is true. 0-1. If 0 or 1, -* the normal will follow exactly. -* @property {boolean} [enabled=false] -* @property {Pointers.ParabolaPointerRenderState[]|Object.} [renderStates] A collection of different visual states to switch between. -* When using {@link Pointers.createPointer}, a list of ParabolaPointerRenderStates. -* When returned from {@link Pointers.getPointerProperties}, a map between render state names and ParabolaPointerRenderStates. -* @property {Pointers.DefaultParabolaPointerRenderState[]|Object.} [defaultRenderStates] A collection of different visual states to use if there is no intersection. -* When using {@link Pointers.createPointer}, a list of DefaultParabolaPointerRenderStates. -* When returned from {@link Pointers.getPointerProperties}, a map between render state names and DefaultParabolaPointerRenderStates. -* @property {boolean} [hover=false] If this Pointer should generate hover events. -* @property {Pointers.Trigger[]} [triggers] A list of different triggers mechanisms that control this Pointer's click event generation. -*/ + * The properties of a parabola pointer. These include the properties from the underlying parabola pick that the pointer uses. + * @typedef {object} Pointers.ParabolaPointerProperties + * @property {boolean} [faceAvatar=false] - true if the overlay rendered at the end of the ray rotates about the + * world y-axis to always face the avatar; false if it maintains its world orientation. + * @property {boolean} [centerEndY=true] - true if the overlay rendered at the end of the ray is centered on + * the ray end; false if the overlay is positioned against the surface if followNormal is + * true, or above the ray end if followNormal is false. +* @property {boolean} [lockEnd=false] - true if the end of the ray is locked to the center of the object at + * which the ray is pointing; false if the end of the ray is at the intersected surface. + * @property {boolean} [distanceScaleEnd=false] - true if the dimensions of the overlay at the end of the ray + * scale linearly with distance; false if they aren't. + * @property {boolean} [scaleWithParent=false] - true if the width of the ray's path and the size of the + * start and end overlays scale linearly with the pointer parent's scale; false if they don't scale. + * @property {boolean} [scaleWithAvatar=false] - A synonym for scalewithParent. + *

Deprecated: This property is deprecated and will be removed.

+ * @property {boolean} [followNormal=false] - true if the overlay rendered at the end of the ray rotates to + * follow the normal of the surface if one is intersected; false if it doesn't. + * @property {number} [followNormalStrength=0.0] - How quickly the overlay rendered at the end of the ray rotates to follow + * the normal of an intersected surface. If 0 or 1, the overlay rotation follows instantaneously; + * for other values, the larger the value the more quickly the rotation follows. + * @property {Pointers.ParabolaPointerRenderState[]|Object.} [renderStates] + *

A set of visual states that can be switched among using {@link Pointers.setRenderState}. These define the visual + * appearance of the pointer when it is intersecting something.

+ *

When setting using {@link Pointers.createPointer}, an array of + * {@link Pointers.ParabolaPointerRenderState|ParabolaPointerRenderState} values.

+ *

When getting using {@link Pointers.getPointerProperties}, an object mapping render state names to + * {@link Pointers.ParabolaPointerRenderState|ParabolaPointerRenderState} values.

+ * @property {Pointers.DefaultParabolaPointerRenderState[]|Object.} + * [defaultRenderStates] + *

A set of visual states that can be switched among using {@link Pointers.setRenderState}. These define the visual + * appearance of the pointer when it is not intersecting something.

+ *

When setting using {@link Pointers.createPointer}, an array of + * {@link Pointers.DefaultParabolaPointerRenderState|DefaultParabolaPointerRenderState} values.

+ *

When getting using {@link Pointers.getPointerProperties}, an object mapping render state names to + * {@link Pointers.DefaultParabolaPointerRenderState|DefaultParabolaPointerRenderState} values.

+ * @property {boolean} [hover=false] - true if the pointer generates {@link Entities} hover events, + * false if it doesn't. + * @property {Pointers.Trigger[]} [triggers=[]] - A list of ways that a {@link Controller} action or function should trigger + * events on the entity or overlay currently intersected. + * @see {@link Picks.ParabolaPickProperties} for additional properties from the underlying parabola pick. + */ unsigned int PointerScriptingInterface::createParabolaPointer(const QVariant& properties) const { QVariantMap propertyMap = properties.toMap(); diff --git a/interface/src/raypick/PointerScriptingInterface.h b/interface/src/raypick/PointerScriptingInterface.h index 268b178fb6..e6efaae09f 100644 --- a/interface/src/raypick/PointerScriptingInterface.h +++ b/interface/src/raypick/PointerScriptingInterface.h @@ -15,8 +15,9 @@ #include /**jsdoc - * The Pointers API lets you create and manage objects for repeatedly calculating intersections in different ways, as well as the visual representation of those objects. - * Pointers can also be configured to automatically generate {@link PointerEvent}s on {@link Entities}. + * The Pointers API lets you create, manage, and visually represent objects for repeatedly calculating + * intersections with avatars, entities, and overlays. Pointers can also be configured to generate events on entities and + * overlays intersected. * * @namespace Pointers * @@ -35,184 +36,416 @@ public: unsigned int createParabolaPointer(const QVariant& properties) const; /**jsdoc - * A trigger mechanism for Ray and Parabola Pointers. - * - * @typedef {object} Pointers.Trigger - * @property {Controller.Standard|Controller.Actions|function} action This can be a built-in Controller action, like Controller.Standard.LTClick, or a function that evaluates to >= 1.0 when you want to trigger button. - * @property {string} button Which button to trigger. "Primary", "Secondary", "Tertiary", and "Focus" are currently supported. Only "Primary" will trigger clicks on web surfaces. If "Focus" is triggered, - * it will try to set the entity focus to the object at which the Pointer is aimed. Buttons besides the first three will still trigger events, but event.button will be "None". - */ + * Specifies that a {@link Controller} action or function should trigger events on the entity or overlay currently + * intersected by a {@link Pointers.RayPointerProperties|Ray} or {@link Pointers.ParabolaPointerProperties|Parabola} + * pointer. + * @typedef {object} Pointers.Trigger + * @property {Controller.Standard|Controller.Actions|function} action - The controller output or function that triggers the + * events on the entity or overlay. If a function, it must return a number >= 1.0 to start the action + * and < 1.0 to terminate the action. + * @property {string} button - Which button to trigger. + *
    + *
  • "Primary", "Secondary", and "Tertiary" cause {@link Entities} and + * {@link Overlays} mouse pointer events. Other button names also cause mouse events but the button + * property in the event will be "None".
  • + *
  • "Focus" will try to give focus to the entity or overlay which the pointer is intersecting.
  • + *
+ */ /**jsdoc - * Adds a new Pointer - * Different {@link PickType}s use different properties, and within one PickType, the properties you choose can lead to a wide range of behaviors. For example, - * with PickType.Ray, depending on which optional parameters you pass, you could create a Static Ray Pointer, a Mouse Ray Pointer, or a Joint Ray Pointer. - * Pointers created with this method always intersect at least visible and collidable things + * Creates a new ray, parabola, or stylus pointer. The pointer can have a wide range of behaviors depending on the + * properties specified. For example, a ray pointer may be a static ray pointer, a mouse ray pointer, or joint ray + * pointer. + *

Warning: Pointers created using this method currently always intersect at least visible and + * collidable things but this may not always be the case.

* @function Pointers.createPointer - * @param {PickType} type A PickType that specifies the method of picking to use. Cannot be {@link PickType|PickType.Collision}. - * @param {Pointers.LaserPointerProperties|Pointers.StylusPointerProperties|Pointers.ParabolaPointerProperties} properties A PointerProperties object, containing all the properties for initializing this Pointer and the {@link Picks.PickProperties} for the Pick that - * this Pointer will use to do its picking. - * @returns {number} The ID of the created Pointer. Used for managing the Pointer. 0 if invalid. + * @param {PickType} type - The type of pointer to create. Cannot be {@link PickType|PickType.Collision}. + * @param {Pointers.RayPointerProperties|Pointers.ParabolaPointerProperties|Pointers.StylusPointerProperties} properties - + * The properties of the pointer, per the pointer type, including the properties of the underlying pick + * that the pointer uses to do its picking. + * @returns {number} The ID of the pointer if successfully created, otherwise 0. * - * @example Create a left hand Ray Pointer that triggers events on left controller trigger click and changes color when it's intersecting something. - * - * var end = { + * @example Create a ray pointer on the left hand that changes color when it's intersecting and that triggers + * events.
+ * Note: Stop controllerScripts.js from running to disable similar behavior from it. + * var intersectEnd = { * type: "sphere", - * dimensions: {x:0.5, y:0.5, z:0.5}, + * dimensions: { x: 0.2, y: 0.2, z: 0.2 }, * solid: true, - * color: {red:0, green:255, blue:0}, + * color: { red: 0, green: 255, blue: 0 }, * ignorePickIntersection: true * }; - * var end2 = { + * var intersectedPath = { + * type: "line3d", + * color: { red: 0, green: 255, blue: 0 }, + * }; + * var searchEnd = { * type: "sphere", - * dimensions: {x:0.5, y:0.5, z:0.5}, + * dimensions: { x: 0.2, y: 0.2, z: 0.2 }, * solid: true, - * color: {red:255, green:0, blue:0}, + * color: { red: 255, green: 0, blue: 0 }, * ignorePickIntersection: true * }; - * - * var renderStates = [ {name: "test", end: end} ]; - * var defaultRenderStates = [ {name: "test", distance: 10.0, end: end2} ]; - * var pointer = Pointers.createPointer(PickType.Ray, { + * var searchPath = { + * type: "line3d", + * color: { red: 255, green: 0, blue: 0 }, + * }; + * + * var renderStates = [{ name: "example", path: intersectedPath, end: intersectEnd }]; + * var defaultRenderStates = [{ name: "example", distance: 20.0, path: searchPath, end: searchEnd }]; + * + * // Create the pointer. + * var rayPointer = Pointers.createPointer(PickType.Ray, { * joint: "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", * filter: Picks.PICK_LOCAL_ENTITIES | Picks.PICK_DOMAIN_ENTITIES | Picks.PICK_INCLUDE_NONCOLLIDABLE, * renderStates: renderStates, * defaultRenderStates: defaultRenderStates, - * distanceScaleEnd: true, - * triggers: [ {action: Controller.Standard.LTClick, button: "Focus"}, {action: Controller.Standard.LTClick, button: "Primary"} ], - * hover: true, + * hover: true, // Generate hover events. + * triggers: [ + * { action: Controller.Standard.LTClick, button: "Primary" }, // Generate mouse events. + * { action: Controller.Standard.LTClick, button: "Focus" } // Focus on web entities. + * ], * enabled: true * }); - * Pointers.setRenderState(pointer, "test"); + * Pointers.setRenderState(rayPointer, "example"); + * + * // Hover events. + * Entities.hoverEnterEntity.connect(function (entityID, event) { + * print("hoverEnterEntity() : " + entityID); + * }); + * Entities.hoverLeaveEntity.connect(function (entityID, event) { + * print("hoverLeaveEntity() : " + entityID); + * }); + * + * // Mouse events. + * Entities.mousePressOnEntity.connect(function (entityID, event) { + * print("mousePressOnEntity() : " + entityID + " , " + event.button); + * }); + * Entities.mouseReleaseOnEntity.connect(function (entityID, event) { + * print("mouseReleaseOnEntity() : " + entityID + " , " + event.button); + * }); + * + * // Tidy up. + * Script.scriptEnding.connect(function () { + * Pointers.removePointer(rayPointer); + * }); */ // TODO: expand Pointers to be able to be fully configurable with PickFilters Q_INVOKABLE unsigned int createPointer(const PickQuery::PickType& type, const QVariant& properties); /**jsdoc - * Enables a Pointer. + * Enables and shows a pointer. Enabled pointers update their pick results and generate events. * @function Pointers.enablePointer - * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. + * @param {number} id - The ID of the pointer. */ Q_INVOKABLE void enablePointer(unsigned int uid) const { DependencyManager::get()->enablePointer(uid); } /**jsdoc - * Disables a Pointer. + * Disables and hides a pointer. Disabled pointers do not update their pick results or generate events. * @function Pointers.disablePointer - * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. + * @param {number} id - The ID of the pointer. */ Q_INVOKABLE void disablePointer(unsigned int uid) const { DependencyManager::get()->disablePointer(uid); } /**jsdoc - * Removes a Pointer. + * Removes (deletes) a pointer. * @function Pointers.removePointer - * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. + * @param {number} id - The ID of the pointer. */ Q_INVOKABLE void removePointer(unsigned int uid) const { DependencyManager::get()->removePointer(uid); } /**jsdoc - * Edit some visual aspect of a Pointer. Currently only supported for Ray Pointers. + * Edits a render state of a {@link Pointers.RayPointerProperties|ray} or + * {@link Pointers.ParabolaPointerProperties|parabola} pointer, to change its visual appearance for the state when the + * pointer is intersecting something. + *

Note: You can only edit the properties of the existing parts of the pointer; you cannot change the + * type of any part.

+ *

Note: You cannot use this method to change the appearance of a default render state.

+ *

Note: Not able to be used with stylus pointers.

* @function Pointers.editRenderState - * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. - * @param {string} renderState The name of the render state you want to edit. - * @param {Pointers.RayPointerRenderState} properties The new properties for renderStates item. + * @param {number} id - The ID of the pointer. + * @param {string} renderState - The name of the render state to edit. + * @param {Pointers.RayPointerRenderState|Pointers.ParabolaPointerRenderState} properties - The new properties for the + * render state. Only the overlay properties to change need be specified. + * @example Change the dimensions of a ray pointer's intersecting end overlay. + * var intersectEnd = { + * type: "sphere", + * dimensions: { x: 0.2, y: 0.2, z: 0.2 }, + * solid: true, + * color: { red: 0, green: 255, blue: 0 }, + * ignorePickIntersection: true + * }; + * var intersectedPath = { + * type: "line3d", + * color: { red: 0, green: 255, blue: 0 }, + * }; + * var searchEnd = { + * type: "sphere", + * dimensions: { x: 0.2, y: 0.2, z: 0.2 }, + * solid: true, + * color: { red: 255, green: 0, blue: 0 }, + * ignorePickIntersection: true + * }; + * var searchPath = { + * type: "line3d", + * color: { red: 255, green: 0, blue: 0 }, + * }; + * + * var renderStates = [ { name: "example", path: intersectedPath, end: intersectEnd } ]; + * var defaultRenderStates = [ { name: "example", distance: 20.0, path: searchPath, end: searchEnd } ]; + * + * // Create the pointer. + * var rayPointer = Pointers.createPointer(PickType.Ray, { + * joint: "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", + * filter: Picks.PICK_LOCAL_ENTITIES | Picks.PICK_DOMAIN_ENTITIES | Picks.PICK_INCLUDE_NONCOLLIDABLE, + * renderStates: renderStates, + * defaultRenderStates: defaultRenderStates, + * enabled: true + * }); + * Pointers.setRenderState(rayPointer, "example"); + * + * // Edit the intersecting render state. + * Script.setTimeout(function () { + * print("Edit render state"); + * Pointers.editRenderState(rayPointer, "example", { + * end: { dimensions: { x: 0.5, y: 0.5, z: 0.5 } } + * }); + * }, 10000); + * + * Script.setTimeout(function () { + * print("Edit render state"); + * Pointers.editRenderState(rayPointer, "example", { + * end: { dimensions: { x: 0.2, y: 0.2, z: 0.2 } } + * }); + * }, 15000); + * + * // Tidy up. + * Script.scriptEnding.connect(function () { + * Pointers.removePointer(rayPointer); + * }); */ Q_INVOKABLE void editRenderState(unsigned int uid, const QString& renderState, const QVariant& properties) const; /**jsdoc - * Set the render state of a Pointer. For Ray Pointers, this means switching between their {@link Pointers.RayPointerRenderState}s, or "" to turn off rendering and hover/trigger events. - * For Stylus Pointers, there are three built-in options: "events on" (render and send events, the default), "events off" (render but don't send events), and "disabled" (don't render, don't send events). + * Sets the render state of a pointer, to change its visual appearance and possibly disable or enable it. * @function Pointers.setRenderState - * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. - * @param {string} renderState The name of the render state to which you want to switch. + * @param {number} id - The ID of the pointer. + * @param {string} renderState -

The name of the render state to set the pointer to.

+ *

For {@link Pointers.RayPointerProperties|ray} and {@link Pointers.ParabolaPointerProperties|parabola} pointers, + * this may be:

+ *
    + *
  • The name of one of the render states set in the pointer's properties.
  • + *
  • "", to hide the pointer and disable emitting of events.
  • + *
+ *

For {@link Pointers.StylusPointerProperties|stylus} pointers, the values may be:

+ *
    + *
  • "events on", to render and emit events (the default).
  • + *
  • "events off", to render but don't emit events.
  • + *
  • "disabled", to not render and not emit events.
  • + *
+ * @example Switch a ray pointer between having a path and not having a path. + * var intersectEnd = { + * type: "sphere", + * dimensions: { x: 0.2, y: 0.2, z: 0.2 }, + * solid: true, + * color: { red: 0, green: 255, blue: 0 }, + * ignorePickIntersection: true + * }; + * var intersectedPath = { + * type: "line3d", + * color: { red: 0, green: 255, blue: 0 }, + * }; + * var searchEnd = { + * type: "sphere", + * dimensions: { x: 0.2, y: 0.2, z: 0.2 }, + * solid: true, + * color: { red: 255, green: 0, blue: 0 }, + * ignorePickIntersection: true + * }; + * var searchPath = { + * type: "line3d", + * color: { red: 255, green: 0, blue: 0 }, + * }; + * + * var renderStates = [ + * { name: "examplePath", path: intersectedPath, end: intersectEnd }, + * { name: "exampleNoPath", end: intersectEnd } + * ]; + * var defaultRenderStates = [ + * { name: "examplePath", distance: 20.0, path: searchPath, end: searchEnd }, + * { name: "exampleNoPath", distance: 20.0, end: searchEnd } + * ]; + * + * // Create the pointer. + * var rayPointer = Pointers.createPointer(PickType.Ray, { + * joint: "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", + * filter: Picks.PICK_LOCAL_ENTITIES | Picks.PICK_DOMAIN_ENTITIES | Picks.PICK_INCLUDE_NONCOLLIDABLE, + * renderStates: renderStates, + * defaultRenderStates: defaultRenderStates, + * enabled: true + * }); + * Pointers.setRenderState(rayPointer, "examplePath"); + * + * // Change states. + * Script.setTimeout(function () { + * print("Without path"); + * Pointers.setRenderState(rayPointer, "exampleNoPath"); + * }, 10000); + * + * Script.setTimeout(function () { + * print("With path"); + * Pointers.setRenderState(rayPointer, "examplePath"); + * }, 15000); + * + * // Tidy up. + * Script.scriptEnding.connect(function () { + * Pointers.removePointer(rayPointer); + * }); */ Q_INVOKABLE void setRenderState(unsigned int uid, const QString& renderState) const { DependencyManager::get()->setRenderState(uid, renderState.toStdString()); } /**jsdoc - * Get the most recent pick result from this Pointer. This will be updated as long as the Pointer is enabled, regardless of the render state. + * Gets the most recent intersection of a pointer. A pointer continues to be updated ready to return a result, as long as + * it is enabled, regardless of the render state. * @function Pointers.getPrevPickResult - * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. - * @returns {RayPickResult|StylusPickResult} The most recent intersection result. This will be slightly different for different PickTypes. + * @param {number} id - The ID of the pointer. + * @returns {RayPickResult|ParabolaPickResult|StylusPickResult} The most recent intersection of the pointer. */ Q_INVOKABLE QVariantMap getPrevPickResult(unsigned int uid) const; /**jsdoc - * Sets whether or not to use precision picking. + * Sets whether or not a pointer should use precision picking, i.e., whether it should pick against precise meshes or + * coarse meshes. This has the same effect as using the PICK_PRECISE or PICK_COARSE filter flags. * @function Pointers.setPrecisionPicking - * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. - * @param {boolean} precisionPicking Whether or not to use precision picking + * @param {number} id - The ID of the pointer. + * @param {boolean} precisionPicking - true to use precision picking, false to use coarse picking. */ Q_INVOKABLE void setPrecisionPicking(unsigned int uid, bool precisionPicking) const { DependencyManager::get()->setPrecisionPicking(uid, precisionPicking); } /**jsdoc - * Sets the length of this Pointer. No effect on Stylus Pointers. + * Sets the length of a pointer. + *

Note: Not used by stylus pointers.

* @function Pointers.setLength - * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. - * @param {number} length The desired length of the Pointer. + * @param {number} id - The ID of the pointer. + * @param {number} length - The desired length of the pointer. */ Q_INVOKABLE void setLength(unsigned int uid, float length) const { DependencyManager::get()->setLength(uid, length); } /**jsdoc - * Sets a list of Entity IDs and/or Avatar IDs to ignore during intersection. Not used by Stylus Pointers. + * Sets a list of entity and avatar IDs that a pointer should ignore during intersection. + *

Note: Not used by stylus pointers.

* @function Pointers.setIgnoreItems - * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. - * @param {Uuid[]} ignoreItems A list of IDs to ignore. + * @param {number} id - The ID of the pointer. + * @param {Uuid[]} ignoreItems - A list of IDs to ignore. */ Q_INVOKABLE void setIgnoreItems(unsigned int uid, const QScriptValue& ignoreEntities) const; /**jsdoc - * Sets a list of Entity IDs and/or Avatar IDs to include during intersection, instead of intersecting with everything. Stylus - * Pointers only intersect with objects in their include list. + * Sets a list of entity and avatar IDs that a pointer should include during intersection, instead of intersecting with + * everything. + *

Note: Stylus pointers only intersect with items in their include list.

* @function Pointers.setIncludeItems - * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. - * @param {Uuid[]} includeItems A list of IDs to include. + * @param {number} id - The ID of the pointer. + * @param {Uuid[]} includeItems - A list of IDs to include. */ Q_INVOKABLE void setIncludeItems(unsigned int uid, const QScriptValue& includeEntities) const; /**jsdoc - * Lock a Pointer onto a specific object (entity or avatar). Optionally, provide an offset in object-space, otherwise the Pointer will lock on to the center of the object. - * Not used by Stylus Pointers. + * Locks a pointer onto a specific entity or avatar. + *

Note: Not used by stylus pointers.

* @function Pointers.setLockEndUUID - * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. - * @param {Uuid} objectID The ID of the object to which to lock on. - * @param {boolean} isAvatar False for entities, true for avatars - * @param {Mat4} [offsetMat] The offset matrix to use if you do not want to lock on to the center of the object. + * @param {number} id - The ID of the pointer. + * @param {Uuid} targetID - The ID of the entity or avatar to lock the pointer on to. + * @param {boolean} isAvatar - true if the target is an avatar, false if it is an entity. + * @param {Mat4} [offset] - The offset of the target point from the center of the target item. If not specified, the + * pointer locks on to the center of the target item. */ Q_INVOKABLE void setLockEndUUID(unsigned int uid, const QUuid& objectID, bool isAvatar, const glm::mat4& offsetMat = glm::mat4()) const { DependencyManager::get()->setLockEndUUID(uid, objectID, isAvatar, offsetMat); } /**jsdoc - * Check if a Pointer is associated with the left hand. + * Checks if a pointer is associated with the left hand: a ray or parabola pointer with joint property set to + * "_CONTROLLER_LEFTHAND" or "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", or a stylus pointer with + * hand property set to 0. * @function Pointers.isLeftHand - * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. - * @returns {boolean} True if the Pointer is a Joint Ray Pointer with joint == "_CONTROLLER_LEFTHAND" or "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", or a Stylus Pointer with hand == 0 + * @param {number} id - The ID of the pointer. + * @returns {boolean} true if the pointer is associated with the left hand, false if it isn't. */ Q_INVOKABLE bool isLeftHand(unsigned int uid) { return DependencyManager::get()->isLeftHand(uid); } /**jsdoc - * Check if a Pointer is associated with the right hand. + * Checks if a pointer is associated with the right hand: a ray or parabola pointer with joint property set to + * "_CONTROLLER_RIGHTHAND" or "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND", or a stylus pointer with + * hand property set to 1. * @function Pointers.isRightHand - * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. - * @returns {boolean} True if the Pointer is a Joint Ray Pointer with joint == "_CONTROLLER_RIGHTHAND" or "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND", or a Stylus Pointer with hand == 1 + * @param {number} id - The ID of the pointer. + * @returns {boolean} true if the pointer is associated with the right hand, false if it isn't. */ Q_INVOKABLE bool isRightHand(unsigned int uid) { return DependencyManager::get()->isRightHand(uid); } /**jsdoc - * Check if a Pointer is associated with the system mouse. + * Checks if a pointer is associated with the system mouse: a ray or parabola pointer with joint property set + * to "Mouse". * @function Pointers.isMouse - * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. - * @returns {boolean} True if the Pointer is a Mouse Ray Pointer, false otherwise. + * @param {number} id - The ID of the pointer. + * @returns {boolean} true if the pointer is associated with the system mouse, false if it isn't. */ Q_INVOKABLE bool isMouse(unsigned int uid) { return DependencyManager::get()->isMouse(uid); } /**jsdoc - * Returns information about an existing Pointer + * Gets information about a pointer. * @function Pointers.getPointerProperties - * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. - * @returns {Pointers.LaserPointerProperties|Pointers.StylusPointerProperties|Pointers.ParabolaPointerProperties} The information about the Pointer. - * Currently only includes renderStates and defaultRenderStates with associated entity IDs. + * @param {number} id - The ID of the pointer. + * @returns {Pointers.RayPointerProperties|Pointers.ParabolaPointerProperties|object} The renderStates and + * defaultRenderStates for ray and parabola pointers, {} for stylus pointers. + * @example Report the properties of a parabola pointer. + * var intersectEnd = { + * type: "sphere", + * dimensions: { x: 0.2, y: 0.2, z: 0.2 }, + * solid: true, + * color: { red: 0, green: 255, blue: 0 }, + * ignorePickIntersection: true + * }; + * var intersectedPath = { + * color: { red: 0, green: 255, blue: 0 }, + * }; + * var searchEnd = { + * type: "sphere", + * dimensions: { x: 0.2, y: 0.2, z: 0.2 }, + * solid: true, + * color: { red: 255, green: 0, blue: 0 }, + * ignorePickIntersection: true + * }; + * var searchPath = { + * color: { red: 255, green: 0, blue: 0 }, + * }; + * + * var renderStates = [{ name: "example", path: intersectedPath, end: intersectEnd }]; + * var defaultRenderStates = [{ name: "example", distance: 20.0, path: searchPath, end: searchEnd }]; + * + * // Create the pointer. + * var parabolaPointer = Pointers.createPointer(PickType.Parabola, { + * joint: "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", + * filter: Picks.PICK_LOCAL_ENTITIES | Picks.PICK_DOMAIN_ENTITIES | Picks.PICK_INCLUDE_NONCOLLIDABLE, + * renderStates: renderStates, + * defaultRenderStates: defaultRenderStates, + * enabled: true + * }); + * Pointers.setRenderState(parabolaPointer, "example"); + * + * // Report the pointer properties. + * Script.setTimeout(function () { + * var properties = Pointers.getPointerProperties(parabolaPointer); + * print("Pointer properties:" + JSON.stringify(properties)); + * }, 500); + * + * // Tidy up. + * Script.scriptEnding.connect(function () { + * Pointers.removePointer(parabolaPointer); + * }); */ Q_INVOKABLE QVariantMap getPointerProperties(unsigned int uid) const; }; diff --git a/interface/src/raypick/RayPickScriptingInterface.h b/interface/src/raypick/RayPickScriptingInterface.h index 32a2ec4a5d..2a00847510 100644 --- a/interface/src/raypick/RayPickScriptingInterface.h +++ b/interface/src/raypick/RayPickScriptingInterface.h @@ -107,7 +107,8 @@ public: /**jsdoc - * Sets whether or not to use precision picking, i.e., whether to pick against precise meshes or coarse meshes. + * Sets whether or not a ray pick should use precision picking, i.e., whether it should pick against precise meshes or + * coarse meshes. * @function RayPick.setPrecisionPicking * @param {number} id - The ID of the ray pick. * @param {boolean} precisionPicking - true to use precision picking, false to use coarse picking. @@ -115,7 +116,7 @@ public: Q_INVOKABLE void setPrecisionPicking(unsigned int uid, bool precisionPicking); /**jsdoc - * Sets a list of entity and avatar IDs to ignore during intersection. + * Sets a list of entity and avatar IDs that a ray pick should ignore during intersection. * @function RayPick.setIgnoreItems * @param {number} id - The ID of the ray pick. * @param {Uuid[]} ignoreItems - The list of IDs to ignore. @@ -123,7 +124,8 @@ public: Q_INVOKABLE void setIgnoreItems(unsigned int uid, const QScriptValue& ignoreEntities); /**jsdoc - * Sets a list of entity IDs and/or avatar IDs to include during intersection, instead of intersecting with everything. + * Sets a list of entity and avatar IDs that a ray pick should include during intersection, instead of intersecting with + * everything. * @function RayPick.setIncludeItems * @param {number} id - The ID of the ray pick. * @param {Uuid[]} includeItems - The list of IDs to include. @@ -132,9 +134,9 @@ public: /**jsdoc - * Checks if a pick is associated with the left hand: a ray or parabola pick with joint set to - * "_CONTROLLER_LEFTHAND" or "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", or a stylus pick with hand - * set to 0. + * Checks if a pick is associated with the left hand: a ray or parabola pick with joint property set to + * "_CONTROLLER_LEFTHAND" or "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", or a stylus pick with + * hand property set to 0. * @function RayPick.isLeftHand * @param {number} id - The ID of the ray pick. * @returns {boolean} true if the pick is associated with the left hand, false if it isn't. @@ -142,9 +144,9 @@ public: Q_INVOKABLE bool isLeftHand(unsigned int uid); /**jsdoc - * Checks if a pick is associated with the right hand: a ray or parabola pick with joint set to - * "_CONTROLLER_RIGHTHAND" or "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND", or a stylus pick with hand - * set to 1. + * Checks if a pick is associated with the right hand: a ray or parabola pick with joint property set to + * "_CONTROLLER_RIGHTHAND" or "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND", or a stylus pick with + * hand property set to 1. * @function RayPick.isRightHand * @param {number} id - The ID of the ray pick. * @returns {boolean} true if the pick is associated with the right hand, false if it isn't. @@ -152,7 +154,8 @@ public: Q_INVOKABLE bool isRightHand(unsigned int uid); /**jsdoc - * Checks if a pick is associated with the system mouse: a ray or parabola pick with joint set to "Mouse". + * Checks if a pick is associated with the system mouse: a ray or parabola pick with joint property set to + * "Mouse". * @function RayPick.isMouse * @param {number} id - The ID of the ray pick. * @returns {boolean} true if the pick is associated with the system mouse, false if it isn't. diff --git a/interface/src/scripting/Audio.cpp b/interface/src/scripting/Audio.cpp index 6df4729ee0..a0bea256ad 100644 --- a/interface/src/scripting/Audio.cpp +++ b/interface/src/scripting/Audio.cpp @@ -366,7 +366,12 @@ void Audio::onContextChanged() { void Audio::handlePushedToTalk(bool enabled) { if (getPTT()) { if (enabled) { - DependencyManager::get()->setOutputGain(0.1f); // duck the output by 20dB + if (!qApp->isHMDMode()) { + float gain = resultWithReadLock([&] { return _pttOutputGainDesktop; }); + // convert dB to amplitude + gain = fastExp2f(gain / 6.02059991f); + DependencyManager::get()->setOutputGain(gain); // duck the output by N dB + } setMuted(false); } else { DependencyManager::get()->setOutputGain(1.0f); @@ -499,3 +504,29 @@ float Audio::getSystemInjectorGain() { return _systemInjectorGain; }); } + +void Audio::setPushingToTalkOutputGainDesktop(float gain) { + if (gain > 0.0f) { + qDebug() << "Denying attempt to set Pushing to Talk Output Gain above 0dB. Attempted value:" << gain; + return; + } + + bool changed = false; + if (getPushingToTalkOutputGainDesktop() != gain) { + changed = true; + } + + withWriteLock([&] { + if (_pttOutputGainDesktop != gain) { + _pttOutputGainDesktop = gain; + } + }); + + if (changed) { + emit pushingToTalkOutputGainDesktopChanged(gain); + } +} + +float Audio::getPushingToTalkOutputGainDesktop() { + return resultWithReadLock([&] { return _pttOutputGainDesktop; }); +} diff --git a/interface/src/scripting/Audio.h b/interface/src/scripting/Audio.h index c7ac98402c..d62fd70cc4 100644 --- a/interface/src/scripting/Audio.h +++ b/interface/src/scripting/Audio.h @@ -66,10 +66,12 @@ class Audio : public AudioScriptingInterface, protected ReadWriteLockable { * @property {boolean} pushToTalkHMD - true if HMD push-to-talk is enabled, otherwise false. * @property {boolean} pushingToTalk - true if the user is currently pushing-to-talk, otherwise * false. - * @property {float} avatarGain - The gain (relative volume) that avatars' voices are played at. This gain is used at the server. - * @property {float} localInjectorGain - The gain (relative volume) that local injectors (local environment sounds) are played at. - * @property {float} serverInjectorGain - The gain (relative volume) that server injectors (server environment sounds) are played at. This gain is used at the server. - * @property {float} systemInjectorGain - The gain (relative volume) that system sounds are played at. + * @property {number} avatarGain - The gain (relative volume) that avatars' voices are played at. This gain is used at the server. + * @property {number} localInjectorGain - The gain (relative volume) that local injectors (local environment sounds) are played at. + * @property {number} serverInjectorGain - The gain (relative volume) that server injectors (server environment sounds) are played at. This gain is used at the server. + * @property {number} systemInjectorGain - The gain (relative volume) that system sounds are played at. + * @property {number} pushingToTalkOutputGainDesktop - The gain (relative volume) that all sounds are played at when the user is holding + * the push-to-talk key in Desktop mode. * * @comment The following properties are from AudioScriptingInterface.h. * @property {boolean} isStereoInput - true if the input audio is being used in stereo, otherwise @@ -94,6 +96,8 @@ class Audio : public AudioScriptingInterface, protected ReadWriteLockable { Q_PROPERTY(bool pushToTalkDesktop READ getPTTDesktop WRITE setPTTDesktop NOTIFY pushToTalkDesktopChanged) Q_PROPERTY(bool pushToTalkHMD READ getPTTHMD WRITE setPTTHMD NOTIFY pushToTalkHMDChanged) Q_PROPERTY(bool pushingToTalk READ getPushingToTalk WRITE setPushingToTalk NOTIFY pushingToTalkChanged) + Q_PROPERTY(float pushingToTalkOutputGainDesktop READ getPushingToTalkOutputGainDesktop + WRITE setPushingToTalkOutputGainDesktop NOTIFY pushingToTalkOutputGainDesktopChanged) Q_PROPERTY(float avatarGain READ getAvatarGain WRITE setAvatarGain NOTIFY avatarGainChanged) Q_PROPERTY(float localInjectorGain READ getLocalInjectorGain WRITE setLocalInjectorGain NOTIFY localInjectorGainChanged) Q_PROPERTY(float serverInjectorGain READ getInjectorGain WRITE setInjectorGain NOTIFY serverInjectorGainChanged) @@ -197,14 +201,14 @@ public: /**jsdoc * Sets the gain (relative volume) that avatars' voices are played at. This gain is used at the server. * @function Audio.setAvatarGain - * @param {number} gain - Avatar gain (dB) at the server. + * @param {number} gain - The avatar gain (dB) at the server. */ Q_INVOKABLE void setAvatarGain(float gain); /**jsdoc * Gets the gain (relative volume) that avatars' voices are played at. This gain is used at the server. * @function Audio.getAvatarGain - * @returns {number} Avatar gain (dB) at the server. + * @returns {number} The avatar gain (dB) at the server. * @example Report current audio gain settings. * // 0 value = normal volume; -ve value = quieter; +ve value = louder. * print("Avatar gain: " + Audio.getAvatarGain()); @@ -217,42 +221,42 @@ public: /**jsdoc * Sets the gain (relative volume) that environment sounds from the server are played at. * @function Audio.setInjectorGain - * @param {number} gain - Injector gain (dB) at the server. + * @param {number} gain - The injector gain (dB) at the server. */ Q_INVOKABLE void setInjectorGain(float gain); /**jsdoc * Gets the gain (relative volume) that environment sounds from the server are played at. * @function Audio.getInjectorGain - * @returns {number} Injector gain (dB) at the server. + * @returns {number} The injector gain (dB) at the server. */ Q_INVOKABLE float getInjectorGain(); /**jsdoc * Sets the gain (relative volume) that environment sounds from the client are played at. * @function Audio.setLocalInjectorGain - * @param {number} gain - Injector gain (dB) in the client. + * @param {number} gain - The injector gain (dB) in the client. */ Q_INVOKABLE void setLocalInjectorGain(float gain); /**jsdoc * Gets the gain (relative volume) that environment sounds from the client are played at. * @function Audio.getLocalInjectorGain - * @returns {number} Injector gain (dB) in the client. + * @returns {number} The injector gain (dB) in the client. */ Q_INVOKABLE float getLocalInjectorGain(); /**jsdoc * Sets the gain (relative volume) that system sounds are played at. * @function Audio.setSystemInjectorGain - * @param {number} gain - Injector gain (dB) in the client. + * @param {number} gain - The injector gain (dB) in the client. */ Q_INVOKABLE void setSystemInjectorGain(float gain); /**jsdoc * Gets the gain (relative volume) that system sounds are played at. * @function Audio.getSystemInjectorGain - * @returns {number} Injector gain (dB) in the client. + * @returns {number} The injector gain (dB) in the client. */ Q_INVOKABLE float getSystemInjectorGain(); @@ -290,6 +294,22 @@ public: */ Q_INVOKABLE bool getRecording(); + /**jsdoc + * Sets the output volume gain that will be used when the user is holding the Push to Talk key. + * Should be negative. + * @function Audio.setPushingToTalkOutputGainDesktop + * @param {number} gain - The output volume gain (dB) while using PTT. + */ + Q_INVOKABLE void setPushingToTalkOutputGainDesktop(float gain); + + /**jsdoc + * Gets the output volume gain that is used when the user is holding the Push to Talk key. + * Should be negative. + * @function Audio.getPushingToTalkOutputGainDesktop + * @returns {number} gain - The output volume gain (dB) while using PTT. + */ + Q_INVOKABLE float getPushingToTalkOutputGainDesktop(); + signals: /**jsdoc @@ -423,7 +443,7 @@ signals: /**jsdoc * Triggered when the avatar gain changes. * @function Audio.avatarGainChanged - * @param {float} gain - The new avatar gain value. + * @param {number} gain - The new avatar gain value. * @returns {Signal} */ void avatarGainChanged(float gain); @@ -431,7 +451,7 @@ signals: /**jsdoc * Triggered when the local injector gain changes. * @function Audio.localInjectorGainChanged - * @param {float} gain - The new local injector gain value. + * @param {number} gain - The new local injector gain value. * @returns {Signal} */ void localInjectorGainChanged(float gain); @@ -447,11 +467,19 @@ signals: /**jsdoc * Triggered when the system injector gain changes. * @function Audio.systemInjectorGainChanged - * @param {float} gain - The new system injector gain value. + * @param {number} gain - The new system injector gain value. * @returns {Signal} */ void systemInjectorGainChanged(float gain); + /**jsdoc + * Triggered when the push to talk gain changes. + * @function Audio.pushingToTalkOutputGainDesktopChanged + * @param {number} gain - The new output gain value. + * @returns {Signal} + */ + void pushingToTalkOutputGainDesktopChanged(float gain); + public slots: /**jsdoc @@ -478,8 +506,9 @@ private: bool _settingsLoaded { false }; float _inputVolume { 1.0f }; float _inputLevel { 0.0f }; - float _localInjectorGain { 0.0f }; // in dB - float _systemInjectorGain { 0.0f }; // in dB + float _localInjectorGain { 0.0f }; // in dB + float _systemInjectorGain { 0.0f }; // in dB + float _pttOutputGainDesktop { 0.0f }; // in dB bool _isClipping { false }; bool _enableNoiseReduction { true }; // Match default value of AudioClient::_isNoiseGateEnabled. bool _enableWarnWhenMuted { true }; diff --git a/interface/src/scripting/DesktopScriptingInterface.cpp b/interface/src/scripting/DesktopScriptingInterface.cpp index 8a34c8f2ba..ef5bd7abb9 100644 --- a/interface/src/scripting/DesktopScriptingInterface.cpp +++ b/interface/src/scripting/DesktopScriptingInterface.cpp @@ -117,5 +117,15 @@ InteractiveWindowPointer DesktopScriptingInterface::createWindow(const QString& Q_ARG(QVariantMap, properties)); return interactiveWindow; } - return new InteractiveWindow(sourceUrl, properties);; + + + // The offscreen surface already validates against non-local QML sources, but we also need to ensure that + // if we create top level QML, like dock widgets or other types of QQuickView containing desktop windows + // that the source URL is permitted + const auto& urlValidator = OffscreenQmlSurface::getUrlValidator(); + if (!urlValidator(sourceUrl)) { + return nullptr; + } + + return new InteractiveWindow(sourceUrl, properties); } diff --git a/interface/src/scripting/PlatformInfoScriptingInterface.cpp b/interface/src/scripting/PlatformInfoScriptingInterface.cpp index 84c4d923d0..cbd94b3dd5 100644 --- a/interface/src/scripting/PlatformInfoScriptingInterface.cpp +++ b/interface/src/scripting/PlatformInfoScriptingInterface.cpp @@ -167,7 +167,9 @@ bool PlatformInfoScriptingInterface::isStandalone() { int PlatformInfoScriptingInterface::getNumCPUs() { return platform::getNumCPUs(); } - +int PlatformInfoScriptingInterface::getMasterCPU() { + return platform::getMasterCPU(); +} QString PlatformInfoScriptingInterface::getCPU(int index) { auto desc = platform::getCPU(index); return QString(desc.dump().c_str()); @@ -176,7 +178,9 @@ QString PlatformInfoScriptingInterface::getCPU(int index) { int PlatformInfoScriptingInterface::getNumGPUs() { return platform::getNumGPUs(); } - +int PlatformInfoScriptingInterface::getMasterGPU() { + return platform::getMasterGPU(); +} QString PlatformInfoScriptingInterface::getGPU(int index) { auto desc = platform::getGPU(index); return QString(desc.dump().c_str()); @@ -185,7 +189,9 @@ QString PlatformInfoScriptingInterface::getGPU(int index) { int PlatformInfoScriptingInterface::getNumDisplays() { return platform::getNumDisplays(); } - +int PlatformInfoScriptingInterface::getMasterDisplay() { + return platform::getMasterDisplay(); +} QString PlatformInfoScriptingInterface::getDisplay(int index) { auto desc = platform::getDisplay(index); return QString(desc.dump().c_str()); diff --git a/interface/src/scripting/PlatformInfoScriptingInterface.h b/interface/src/scripting/PlatformInfoScriptingInterface.h index 113509d6d9..9ac67ec0bd 100644 --- a/interface/src/scripting/PlatformInfoScriptingInterface.h +++ b/interface/src/scripting/PlatformInfoScriptingInterface.h @@ -94,8 +94,8 @@ public slots: * @returns {string} The graphics card type. * @deprecated This function is deprecated and will be removed. * use getNumGPUs() to know the number of GPUs in the hardware, at least one is expected - * use getGPU(0)["vendor"] to get the brand of the vendor - * use getGPU(0)["model"] to get the model name of the gpu + * use getGPU(getMasterGPU())["vendor"] to get the brand of the vendor + * use getGPU(getMasterGPU())["model"] to get the model name of the gpu */ QString getGraphicsCardType(); @@ -135,6 +135,13 @@ public slots: */ int getNumCPUs(); + /**jsdoc + * Get the index of the master CPU. + * @function PlatformInfo.getMasterCPU + * @returns {number} The index of the master CPU detected on the hardware platform. + */ + int getMasterCPU(); + /**jsdoc * Get the description of the CPU at the index parameter * expected fields are: @@ -152,6 +159,13 @@ public slots: */ int getNumGPUs(); + /**jsdoc + * Get the index of the master GPU. + * @function PlatformInfo.getMasterGPU + * @returns {number} The index of the master GPU detected on the hardware platform. + */ + int getMasterGPU(); + /**jsdoc * Get the description of the GPU at the index parameter * expected fields are: @@ -169,6 +183,13 @@ public slots: */ int getNumDisplays(); + /**jsdoc + * Get the index of the master Display. + * @function PlatformInfo.getMasterDisplay + * @returns {number} The index of the master Display detected on the hardware platform. + */ + int getMasterDisplay(); + /**jsdoc * Get the description of the Display at the index parameter * expected fields are: diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index eb967dde89..80c0479bd7 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -638,3 +638,13 @@ void WindowScriptingInterface::setActiveDisplayPlugin(int index) { auto name = PluginManager::getInstance()->getDisplayPlugins().at(index)->getName(); qApp->setActiveDisplayPlugin(name); } + +void WindowScriptingInterface::openWebBrowser() { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "openWebBrowser", Qt::QueuedConnection); + return; + } + + auto offscreenUi = DependencyManager::get(); + offscreenUi->load("Browser.qml"); +} diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index 0c2b494b0b..eab1c65ebb 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -608,6 +608,12 @@ public slots: */ void setActiveDisplayPlugin(int index); + /**jsdoc + * Opens a web browser in a pop-up window. + * @function Window.openWebBrowser + */ + void openWebBrowser(); + private slots: void onWindowGeometryChanged(const QRect& geometry); diff --git a/interface/src/ui/AnimStats.cpp b/interface/src/ui/AnimStats.cpp index d4696a8c04..47116ea281 100644 --- a/interface/src/ui/AnimStats.cpp +++ b/interface/src/ui/AnimStats.cpp @@ -132,7 +132,7 @@ void AnimStats::updateStats(bool force) { if (type == AnimNodeType::Clip) { // figure out the grayScale color of this line. - const float LIT_TIME = 2.0f; + const float LIT_TIME = 20.0f; const float FADE_OUT_TIME = 1.0f; float grayScale = 0.0f; float secondsElapsed = (float)(now - _animAlphaValueChangedTimers[key]) / (float)USECS_PER_SECOND; @@ -176,7 +176,7 @@ void AnimStats::updateStats(bool force) { } // figure out the grayScale color of this line. - const float LIT_TIME = 2.0f; + const float LIT_TIME = 20.0f; const float FADE_OUT_TIME = 0.5f; float grayScale = 0.0f; float secondsElapsed = (float)(now - _animVarChangedTimers[key]) / (float)USECS_PER_SECOND; diff --git a/interface/src/ui/InteractiveWindow.cpp b/interface/src/ui/InteractiveWindow.cpp index 84d24ddeae..dfef16b536 100644 --- a/interface/src/ui/InteractiveWindow.cpp +++ b/interface/src/ui/InteractiveWindow.cpp @@ -32,7 +32,8 @@ static auto CONTENT_WINDOW_QML = QUrl("InteractiveWindow.qml"); -static const char* const FLAGS_PROPERTY = "flags"; +static const char* const ADDITIONAL_FLAGS_PROPERTY = "additionalFlags"; +static const char* const OVERRIDE_FLAGS_PROPERTY = "overrideFlags"; static const char* const SOURCE_PROPERTY = "source"; static const char* const TITLE_PROPERTY = "title"; static const char* const POSITION_PROPERTY = "position"; @@ -92,8 +93,12 @@ void InteractiveWindow::forwardKeyReleaseEvent(int key, int modifiers) { * @property {InteractiveWindow.PresentationWindowInfo} [presentationWindowInfo] - Controls how a NATIVE window is * displayed. If used, the window is docked to the specified edge of the Interface window, otherwise the window is * displayed as its own separate window. - * @property {InteractiveWindow.Flags} [flags=0] - Window behavior flags, set at window creation. Possible flag values are - * provided as {@link Desktop|Desktop.ALWAYS_ON_TOP} and {@link Desktop|Desktop.CLOSE_BUTTON_HIDES}. + * @property {InteractiveWindow.AdditionalFlags} [additionalFlags=0] - Window behavior flags in addition to "native window flags" (minimize/maximize/close), + * set at window creation. Possible flag values are provided as {@link Desktop|Desktop.ALWAYS_ON_TOP} and {@link Desktop|Desktop.CLOSE_BUTTON_HIDES}. + * Additional flag values can be found on Qt's website at https://doc.qt.io/qt-5/qt.html#WindowType-enum. + * @property {InteractiveWindow.OverrideFlags} [overrideFlags=0] - Window behavior flags instead of the default window flags. + * Set at window creation. Possible flag values are provided as {@link Desktop|Desktop.ALWAYS_ON_TOP} and {@link Desktop|Desktop.CLOSE_BUTTON_HIDES}. + * Additional flag values can be found on Qt's website at https://doc.qt.io/qt-5/qt.html#WindowType-enum. */ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap& properties) { InteractiveWindowPresentationMode presentationMode = InteractiveWindowPresentationMode::Native; @@ -179,8 +184,11 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap offscreenUi->loadInNewContext(CONTENT_WINDOW_QML, [&](QQmlContext* context, QObject* object) { _qmlWindow = object; context->setContextProperty(EVENT_BRIDGE_PROPERTY, this); - if (properties.contains(FLAGS_PROPERTY)) { - object->setProperty(FLAGS_PROPERTY, properties[FLAGS_PROPERTY].toUInt()); + if (properties.contains(ADDITIONAL_FLAGS_PROPERTY)) { + object->setProperty(ADDITIONAL_FLAGS_PROPERTY, properties[ADDITIONAL_FLAGS_PROPERTY].toUInt()); + } + if (properties.contains(OVERRIDE_FLAGS_PROPERTY)) { + object->setProperty(OVERRIDE_FLAGS_PROPERTY, properties[OVERRIDE_FLAGS_PROPERTY].toUInt()); } if (properties.contains(PRESENTATION_MODE_PROPERTY)) { object->setProperty(PRESENTATION_MODE_PROPERTY, properties[PRESENTATION_MODE_PROPERTY].toInt()); @@ -201,6 +209,10 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap } connect(object, SIGNAL(sendToScript(QVariant)), this, SLOT(qmlToScript(const QVariant&)), Qt::QueuedConnection); + QObject::connect(object, SIGNAL(keyPressEvent(int, int)), this, SLOT(forwardKeyPressEvent(int, int)), + Qt::QueuedConnection); + QObject::connect(object, SIGNAL(keyReleaseEvent(int, int)), this, SLOT(forwardKeyReleaseEvent(int, int)), + Qt::QueuedConnection); connect(object, SIGNAL(interactiveWindowPositionChanged()), this, SIGNAL(positionChanged()), Qt::QueuedConnection); connect(object, SIGNAL(interactiveWindowSizeChanged()), this, SIGNAL(sizeChanged()), Qt::QueuedConnection); connect(object, SIGNAL(interactiveWindowVisibleChanged()), this, SIGNAL(visibleChanged()), Qt::QueuedConnection); diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index d97c401351..926588e4ca 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -143,10 +143,6 @@ void Snapshot::save360Snapshot(const glm::vec3& cameraPosition, secondaryCameraRenderConfig->enableSecondaryCameraRenderConfigs(true); } - // Initialize some secondary camera render config options for 360 snapshot capture - static_cast(qApp->getRenderEngine()->getConfiguration()->getConfig("SecondaryCameraJob.ToneMapping")) - ->setCurve(0); - secondaryCameraRenderConfig->resetSizeSpectatorCamera(static_cast(CUBEMAP_SIDE_PIXEL_DIMENSION), static_cast(CUBEMAP_SIDE_PIXEL_DIMENSION)); secondaryCameraRenderConfig->setProperty("attachedEntityId", ""); @@ -209,7 +205,6 @@ void Snapshot::takeNextSnapshot() { // Reset secondary camera render config SecondaryCameraJobConfig* config = static_cast(qApp->getRenderEngine()->getConfiguration()->getConfig("SecondaryCamera")); - static_cast(qApp->getRenderEngine()->getConfiguration()->getConfig("SecondaryCameraJob.ToneMapping"))->setCurve(1); config->resetSizeSpectatorCamera(qApp->getWindow()->geometry().width(), qApp->getWindow()->geometry().height()); config->setProperty("attachedEntityId", _oldAttachedEntityId); config->setProperty("vFoV", _oldvFoV); diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 6eaf481efe..1a2382769c 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -77,7 +77,7 @@ public: * @hifi-avatar * * @property {Uuid} keyboardFocusOverlay - Get or set the {@link Entities.EntityTypes|Web} entity that has keyboard focus. - * If no entity has keyboard focus, get returns null; set to null or {@link Uuid(0)|Uuid.NULL} to + * If no entity has keyboard focus, returns null; set to null or {@link Uuid(0)|Uuid.NULL} to * clear keyboard focus. */ diff --git a/launchers/darwin/CMakeLists.txt b/launchers/darwin/CMakeLists.txt index a3fc0dc7c1..0a7ef70461 100644 --- a/launchers/darwin/CMakeLists.txt +++ b/launchers/darwin/CMakeLists.txt @@ -27,6 +27,8 @@ set(src_files src/LatestBuildRequest.m src/OrganizationRequest.m src/OrganizationRequest.h + src/ImageView.m + src/ImageView.h src/Interface.h src/Interface.m src/ErrorViewController.h diff --git a/launchers/darwin/nib/DisplayNameScreen.xib b/launchers/darwin/nib/DisplayNameScreen.xib index 3ba3deba53..94fa739f8e 100644 --- a/launchers/darwin/nib/DisplayNameScreen.xib +++ b/launchers/darwin/nib/DisplayNameScreen.xib @@ -16,13 +16,13 @@ - + - + @@ -70,12 +70,12 @@ - + - - + + - + diff --git a/launchers/darwin/nib/ProcessScreen.xib b/launchers/darwin/nib/ProcessScreen.xib index c6bd8abbec..d16d71e5fa 100644 --- a/launchers/darwin/nib/ProcessScreen.xib +++ b/launchers/darwin/nib/ProcessScreen.xib @@ -16,18 +16,18 @@ - + - + - + @@ -36,7 +36,7 @@ - + @@ -49,6 +49,10 @@ + + + + @@ -56,6 +60,7 @@ + diff --git a/launchers/darwin/nib/SplashScreen.xib b/launchers/darwin/nib/SplashScreen.xib index 3e2e37c81a..3bbed22a59 100644 --- a/launchers/darwin/nib/SplashScreen.xib +++ b/launchers/darwin/nib/SplashScreen.xib @@ -16,7 +16,7 @@ - + diff --git a/launchers/darwin/src/CredentialsRequest.h b/launchers/darwin/src/CredentialsRequest.h index 2e0807c5ba..d1ddfee2df 100644 --- a/launchers/darwin/src/CredentialsRequest.h +++ b/launchers/darwin/src/CredentialsRequest.h @@ -1,10 +1,7 @@ #import -@interface CredentialsRequest : NSObject { +@interface CredentialsRequest : NSObject { } -@property (nonatomic, retain) NSMutableData* webData; -@property (nonatomic, retain) NSString* jsonString; - - (void) confirmCredentials:(NSString*)username :(NSString*)password; @end diff --git a/launchers/darwin/src/CredentialsRequest.m b/launchers/darwin/src/CredentialsRequest.m index a5c24496ec..6d534447f1 100644 --- a/launchers/darwin/src/CredentialsRequest.m +++ b/launchers/darwin/src/CredentialsRequest.m @@ -2,6 +2,11 @@ #import "Launcher.h" #import "Settings.h" +@interface CredentialsRequest () +@property (nonatomic, assign) NSMutableData* receivedData; +@property (nonatomic, assign) NSInteger statusCode; +@end + @implementation CredentialsRequest - (void) confirmCredentials:(NSString*)username :(NSString*)password { @@ -21,77 +26,70 @@ [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:postData]; - NSURLSession* session = [NSURLSession sharedSession]; - NSURLSessionDataTask* dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { - - NSLog(@"credentials request finished"); - NSMutableData* webData = [NSMutableData data]; - [webData appendData:data]; - NSString* jsonString = [[NSString alloc] initWithBytes: [webData mutableBytes] length:[data length] encoding:NSUTF8StringEncoding]; - NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; - id json = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil]; - - Launcher* sharedLauncher = [Launcher sharedLauncher]; - if (json[@"error"] != nil) { - dispatch_async(dispatch_get_main_queue(), ^{ - [[Settings sharedSettings] login:FALSE]; - [sharedLauncher setLoginErrorState: CREDENTIALS]; - [sharedLauncher credentialsAccepted:FALSE]; - }); - } else { - dispatch_async(dispatch_get_main_queue(), ^{ - [[Settings sharedSettings] login:TRUE]; - [sharedLauncher setTokenString:jsonString]; - [sharedLauncher credentialsAccepted:TRUE]; - }); - } - - NSLog(@"credentials: connectionDidFinished completed"); - - }]; - + NSURLSession* session = [NSURLSession sessionWithConfiguration:NSURLSessionConfiguration.ephemeralSessionConfiguration delegate: self delegateQueue: [NSOperationQueue mainQueue]]; + NSURLSessionDataTask* dataTask = [session dataTaskWithRequest:request]; + [dataTask resume]; } -- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { - [self.webData appendData:data]; - NSLog(@"credentials connection received data"); -} -- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { - NSLog(@"credentials connection received response"); +- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response + completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler { + self.receivedData = nil; + self.receivedData = [[NSMutableData alloc] init]; + [self.receivedData setLength:0]; NSHTTPURLResponse *ne = (NSHTTPURLResponse *)response; - if([ne statusCode] == 200) { - NSLog(@"connection state is 200 - all okay"); - } else { - NSLog(@"connection state is NOT 200"); - [[Launcher sharedLauncher] displayErrorPage]; - } + self.statusCode = [ne statusCode]; + NSLog(@"Credentials Response status code: %ld", self.statusCode); + completionHandler(NSURLSessionResponseAllow); } --(void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { - NSLog(@"Conn Err: %@", [error localizedDescription]); - [[Launcher sharedLauncher] displayErrorPage]; + +-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask + didReceiveData:(NSData *)data { + + [self.receivedData appendData:data]; + NSLog(@"Credentials: did recieve data"); } -- (void)connectionDidFinishLoading:(NSURLConnection *)connection { - NSLog(@"credentials request finished"); - NSString* jsonString = [[NSString alloc] initWithBytes: [self.webData mutableBytes] length:[self.webData length] encoding:NSUTF8StringEncoding]; - NSData *data = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; - id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; - +- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { Launcher* sharedLauncher = [Launcher sharedLauncher]; - if (json[@"error"] != nil) { - [[Settings sharedSettings] login:FALSE]; - [sharedLauncher setLoginErrorState: CREDENTIALS]; - [sharedLauncher credentialsAccepted:FALSE]; + if (error) { + NSLog(@"Credentials: Request completed with an error -> error: %@", error); + [sharedLauncher displayErrorPage]; } else { - [[Settings sharedSettings] login:TRUE]; - [sharedLauncher setTokenString:jsonString]; - [sharedLauncher credentialsAccepted:TRUE]; - } - - NSLog(@"credentials: connectionDidFinished completed"); -} + if (self.statusCode == 200) { + NSString* jsonString = [[NSString alloc] initWithBytes: [self.receivedData mutableBytes] length:[self.receivedData length] encoding:NSUTF8StringEncoding]; + NSData* jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; + NSError* jsonError = nil; + id json = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&jsonError]; + if (jsonError) { + NSLog(@"Credentials: Failed to parse json -> error: %@", jsonError); + NSLog(@"Credentials: JSON string from data: %@", jsonString); + [sharedLauncher displayErrorPage]; + return; + } + + if (json[@"error"] != nil) { + NSLog(@"Credentials: Login failed -> error: %@", json[@"error"]); + [[Settings sharedSettings] login:FALSE]; + [sharedLauncher setLoginErrorState: CREDENTIALS]; + [sharedLauncher credentialsAccepted:FALSE]; + } else { + NSLog(@"Credentials: Login succeeded"); + [[Settings sharedSettings] login:TRUE]; + [sharedLauncher setTokenString:jsonString]; + [sharedLauncher credentialsAccepted:TRUE]; + } + } else if (self.statusCode == 403 || self.statusCode == 404 || self.statusCode == 401) { + NSLog(@"Credentials: Log failed with statusCode: %ld", self.statusCode); + [[Settings sharedSettings] login:FALSE]; + [sharedLauncher setLoginErrorState: CREDENTIALS]; + [sharedLauncher credentialsAccepted:FALSE]; + } else { + [sharedLauncher displayErrorPage]; + } + } +} @end diff --git a/launchers/darwin/src/CustomUI.h b/launchers/darwin/src/CustomUI.h index a9d93d03c7..a5e27f5c1b 100644 --- a/launchers/darwin/src/CustomUI.h +++ b/launchers/darwin/src/CustomUI.h @@ -25,6 +25,6 @@ extern NSString* hifiBackgroundFilename; @end @interface Hyperlink : NSTextField { - + } @end diff --git a/launchers/darwin/src/CustomUI.m b/launchers/darwin/src/CustomUI.m index 156efe04d5..61f92fe51f 100644 --- a/launchers/darwin/src/CustomUI.m +++ b/launchers/darwin/src/CustomUI.m @@ -24,19 +24,19 @@ NSString* hifiBackgroundFilename = @"hifi_window"; [NSApp sendAction:(NSSelectorFromString(@"paste:")) to:nil from:self]; return TRUE; } - + if ([[event charactersIgnoringModifiers] isEqualToString:@"c"]) { [NSApp sendAction:(NSSelectorFromString(@"copy:")) to:nil from:self]; return TRUE; } - + if ([[event charactersIgnoringModifiers] isEqualToString:@"a"]) { [NSApp sendAction:(NSSelectorFromString(@"selectAll:")) to:nil from:self]; return TRUE; } } } - + return [super performKeyEquivalent:event]; } @@ -46,7 +46,7 @@ NSString* hifiBackgroundFilename = @"hifi_window"; NSTextView *fieldEditor = (NSTextView*)[self.window fieldEditor:YES forObject:self]; fieldEditor.insertionPointColor = insertionPointColor; - + } -(BOOL)becomeFirstResponder @@ -75,7 +75,7 @@ NSString* hifiBackgroundFilename = @"hifi_window"; NSTextView *fieldEditor = (NSTextView*)[self.window fieldEditor:YES forObject:self]; fieldEditor.insertionPointColor = insertionPointColor; - + } @@ -97,19 +97,19 @@ NSString* hifiBackgroundFilename = @"hifi_window"; [NSApp sendAction:(NSSelectorFromString(@"paste:")) to:nil from:self]; return TRUE; } - + if ([[event charactersIgnoringModifiers] isEqualToString:@"c"]) { [NSApp sendAction:(NSSelectorFromString(@"copy:")) to:nil from:self]; return TRUE; } - + if ([[event charactersIgnoringModifiers] isEqualToString:@"a"]) { [NSApp sendAction:(NSSelectorFromString(@"selectAll:")) to:nil from:self]; return TRUE; } } } - + return [super performKeyEquivalent:event]; } @end @@ -126,7 +126,7 @@ NSString* hifiBackgroundFilename = @"hifi_window"; - (void)awakeFromNib { [super awakeFromNib]; - + self.wantsLayer = YES; self.layer.backgroundColor = [NSColor blackColor].CGColor; self.layer.borderColor = [NSColor whiteColor].CGColor; @@ -134,16 +134,16 @@ NSString* hifiBackgroundFilename = @"hifi_window"; self.layer.masksToBounds = YES; _titleLayer = [[CATextLayer alloc] init]; - + CGSize buttonSize = self.frame.size; CGSize titleSize = [self.title sizeWithAttributes:@{NSFontAttributeName: self.font}]; CGFloat x = (buttonSize.width - titleSize.width) / 2.0; // Title's origin x CGFloat y = (buttonSize.height - titleSize.height) / 2.0; // Title's origin y - + self.titleLayer.frame = NSMakeRect(round(x), round(y), ceil(titleSize.width), ceil(titleSize.height)); self.titleLayer.string = self.title; self.titleLayer.foregroundColor = [NSColor whiteColor].CGColor; - + // TODO(huffman) Fix this to be dynamic based on screen? self.titleLayer.contentsScale = 2.0; @@ -151,7 +151,7 @@ NSString* hifiBackgroundFilename = @"hifi_window"; self.titleLayer.fontSize = self.font.pointSize; //self.titleLayer.allowsEdgeAntialiasing = YES; //self.titleLayer.allowsFontSubpixelQuantization = YES; - + [self.layer addSublayer:self.titleLayer]; } diff --git a/launchers/darwin/src/DownloadDomainContent.h b/launchers/darwin/src/DownloadDomainContent.h index c35c8b8f09..80d03fd1c8 100644 --- a/launchers/darwin/src/DownloadDomainContent.h +++ b/launchers/darwin/src/DownloadDomainContent.h @@ -2,7 +2,10 @@ @interface DownloadDomainContent : NSObject { } - +@property (nonatomic, assign) double progressPercentage; +@property (nonatomic, assign) double taskProgressPercentage; - (void) downloadDomainContent:(NSString*) domainContentUrl; +- (double) getProgressPercentage; + @end diff --git a/launchers/darwin/src/DownloadDomainContent.m b/launchers/darwin/src/DownloadDomainContent.m index 65878db356..f95ae39fc8 100644 --- a/launchers/darwin/src/DownloadDomainContent.m +++ b/launchers/darwin/src/DownloadDomainContent.m @@ -3,12 +3,19 @@ @implementation DownloadDomainContent +- (double) getProgressPercentage +{ + return (self.progressPercentage * 0.70) + (self.taskProgressPercentage * 0.30); +} + - (void) downloadDomainContent:(NSString *)domainContentUrl { + self.progressPercentage = 0.0; + self.taskProgressPercentage = 0.0; NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:domainContentUrl] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0]; - + NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: self delegateQueue: [NSOperationQueue mainQueue]]; NSURLSessionDownloadTask *downloadTask = [defaultSession downloadTaskWithRequest:request]; @@ -17,8 +24,11 @@ -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite { CGFloat prog = (float)totalBytesWritten/totalBytesExpectedToWrite; - NSLog(@"domain content downloaded %d%%", (int)(100.0*prog)); - + NSLog(@"domain content downloaded %f", (100.0*prog)); + + self.progressPercentage = (int)(100.0 * prog); + [[Launcher sharedLauncher] updateProgressIndicator]; + } -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes { @@ -27,7 +37,12 @@ -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location { NSLog(@"Did finish downloading to url"); - NSError *error; + NSTimer* timer = [NSTimer scheduledTimerWithTimeInterval: 0.1 + target: self + selector: @selector(updatePercentage:) + userInfo:nil + repeats: YES]; + NSError *error = nil; NSFileManager *fileManager = [NSFileManager defaultManager]; NSString *destinationFileName = downloadTask.originalRequest.URL.lastPathComponent; NSString* finalFilePath = [[[Launcher sharedLauncher] getDownloadPathForContentAndScripts] stringByAppendingPathComponent:destinationFileName]; @@ -36,27 +51,53 @@ { [fileManager removeItemAtURL:destinationURL error:nil]; } - - NSLog(@"%@", location.path); - NSLog(@"%@", destinationURL); + + NSLog(@"location: %@", location.path); + NSLog(@"destination: %@", destinationURL); BOOL success = [fileManager moveItemAtURL:location toURL:destinationURL error:&error]; - - + + NSLog(success ? @"TRUE" : @"FALSE"); Launcher* sharedLauncher = [Launcher sharedLauncher]; + + if (error) { + NSLog(@"DownlodDomainContent: failed to move file to destintation -> error: %@", error); + [timer invalidate]; + [sharedLauncher displayErrorPage]; + return; + } [sharedLauncher setDownloadContextFilename:destinationFileName]; NSLog(@"extracting domain content file"); - [sharedLauncher extractZipFileAtDestination:[[sharedLauncher getDownloadPathForContentAndScripts] stringByAppendingString:@"content"] :[[sharedLauncher getDownloadPathForContentAndScripts] stringByAppendingString:[sharedLauncher getDownloadContentFilename]]]; - + BOOL extractionSuccessful = [sharedLauncher extractZipFileAtDestination:[[sharedLauncher getDownloadPathForContentAndScripts] stringByAppendingString:@"content"] :[[sharedLauncher getDownloadPathForContentAndScripts] stringByAppendingString:[sharedLauncher getDownloadContentFilename]]]; + + if (!extractionSuccessful) { + [timer invalidate]; + [sharedLauncher displayErrorPage]; + return; + } NSLog(@"finished extracting content file"); + [timer invalidate]; + self.taskProgressPercentage = 100.0; + [sharedLauncher updateProgressIndicator]; [sharedLauncher domainContentDownloadFinished]; } --(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { +- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { NSLog(@"completed; error: %@", error); if (error) { [[Launcher sharedLauncher] displayErrorPage]; } } +- (void) updatePercentage:(NSTimer*) timer { + if (self.taskProgressPercentage < 100.0) { + self.taskProgressPercentage += 1.5; + + if (self.taskProgressPercentage > 100.0) { + self.taskProgressPercentage = 100.0; + } + } + [[Launcher sharedLauncher] updateProgressIndicator]; +} + @end diff --git a/launchers/darwin/src/DownloadInterface.h b/launchers/darwin/src/DownloadInterface.h index 08968f19f0..9d90688654 100644 --- a/launchers/darwin/src/DownloadInterface.h +++ b/launchers/darwin/src/DownloadInterface.h @@ -3,6 +3,10 @@ @interface DownloadInterface : NSObject { } @property (nonatomic, assign) NSString* finalFilePath; +@property (nonatomic, assign) double progressPercentage; +@property (nonatomic, assign) double taskProgressPercentage; - (void) downloadInterface:(NSString*) downloadUrl; + +- (double) getProgressPercentage; @end diff --git a/launchers/darwin/src/DownloadInterface.m b/launchers/darwin/src/DownloadInterface.m index 7a8abf2e0a..f0bdb645da 100644 --- a/launchers/darwin/src/DownloadInterface.m +++ b/launchers/darwin/src/DownloadInterface.m @@ -6,21 +6,31 @@ - (void) downloadInterface:(NSString*) downloadUrl { + self.progressPercentage = 0.0; + self.taskProgressPercentage = 0.0; NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:downloadUrl] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0]; - + NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: self delegateQueue: [NSOperationQueue mainQueue]]; NSURLSessionDownloadTask *downloadTask = [defaultSession downloadTaskWithRequest:request]; - + [downloadTask resume]; } -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite { CGFloat prog = (float)totalBytesWritten/totalBytesExpectedToWrite; NSLog(@"interface downloaded %d%%", (int)(100.0*prog)); - + + self.progressPercentage = (100.0 * prog); + [[Launcher sharedLauncher] updateProgressIndicator]; + +} + +- (double) getProgressPercentage +{ + return (self.progressPercentage * 0.70) + (self.taskProgressPercentage * 0.30); } -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes { @@ -29,7 +39,12 @@ -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location { NSLog(@"Did finish downloading to url"); - NSError *error; + NSTimer* timer = [NSTimer scheduledTimerWithTimeInterval: 0.1 + target: self + selector: @selector(updateTaskPercentage:) + userInfo:nil + repeats: YES]; + NSError *error = nil; NSFileManager *fileManager = [NSFileManager defaultManager]; NSString *destinationFileName = downloadTask.originalRequest.URL.lastPathComponent; NSString* finalFilePath = [[[Launcher sharedLauncher] getAppPath] stringByAppendingPathComponent:destinationFileName]; @@ -39,37 +54,63 @@ [fileManager removeItemAtURL:destinationURL error:nil]; } [fileManager moveItemAtURL:location toURL:destinationURL error:&error]; - + Launcher* sharedLauncher = [Launcher sharedLauncher]; + + if (error) { + NSLog(@"Download Interface: failed to move file to destination -> error: %@", error); + [timer invalidate]; + [sharedLauncher displayErrorPage]; + return; + } [sharedLauncher setDownloadFilename:destinationFileName]; NSString* appPath = [sharedLauncher getAppPath]; NSString* downloadFileName = [sharedLauncher getDownloadFilename]; - + NSLog(@"extract interface zip"); - [sharedLauncher extractZipFileAtDestination:appPath :[appPath stringByAppendingString:downloadFileName]]; + BOOL success = [sharedLauncher extractZipFileAtDestination:appPath :[appPath stringByAppendingString:downloadFileName]]; + if (!success) { + [timer invalidate]; + [sharedLauncher displayErrorPage]; + return; + } NSLog(@"finished extracting interface zip"); - + NSLog(@"starting xattr"); NSTask* quaratineTask = [[NSTask alloc] init]; quaratineTask.launchPath = @"/usr/bin/xattr"; quaratineTask.arguments = @[@"-d", @"com.apple.quarantine", [appPath stringByAppendingString:@"interface.app"]]; - + [quaratineTask launch]; [quaratineTask waitUntilExit]; NSLog(@"finished xattr"); - + NSString* launcherPath = [appPath stringByAppendingString:@"Launcher"]; - + [[Settings sharedSettings] setLauncherPath:launcherPath]; + [timer invalidate]; + self.taskProgressPercentage = 100.0; + [sharedLauncher updateProgressIndicator]; [sharedLauncher interfaceFinishedDownloading]; } -(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { - NSLog(@"completed; error: %@", error); if (error) { + NSLog(@"DownloadInterface: did complete with error -> error: %@", error); [[Launcher sharedLauncher] displayErrorPage]; } } +- (void) updateTaskPercentage:(NSTimer*) timer { + if (self.taskProgressPercentage < 100.0) { + self.taskProgressPercentage += 1.5; + + if (self.taskProgressPercentage > 100.0) { + self.taskProgressPercentage = 100.0; + } + } + [[Launcher sharedLauncher] updateProgressIndicator]; +} + @end diff --git a/launchers/darwin/src/ErrorViewController.m b/launchers/darwin/src/ErrorViewController.m index 0ae321763f..84dee95678 100644 --- a/launchers/darwin/src/ErrorViewController.m +++ b/launchers/darwin/src/ErrorViewController.m @@ -20,7 +20,7 @@ -(IBAction)resartLauncher:(id)sender { - [[Launcher sharedLauncher] showLoginScreen]; + [[Launcher sharedLauncher] restart]; } @end diff --git a/launchers/darwin/src/ImageView.h b/launchers/darwin/src/ImageView.h new file mode 100644 index 0000000000..2def447099 --- /dev/null +++ b/launchers/darwin/src/ImageView.h @@ -0,0 +1,6 @@ +#import + +@interface ImageView : NSImageView +{ +} +@end diff --git a/launchers/darwin/src/ImageView.m b/launchers/darwin/src/ImageView.m new file mode 100644 index 0000000000..f8b0a4b928 --- /dev/null +++ b/launchers/darwin/src/ImageView.m @@ -0,0 +1,11 @@ +#import "ImageView.h" + +@implementation ImageView + +- (BOOL) mouseDownCanMoveWindow +{ + return TRUE; +} + + +@end diff --git a/launchers/darwin/src/LatestBuildRequest.m b/launchers/darwin/src/LatestBuildRequest.m index 0c136dce3c..deb6d9795b 100644 --- a/launchers/darwin/src/LatestBuildRequest.m +++ b/launchers/darwin/src/LatestBuildRequest.m @@ -28,17 +28,22 @@ [request setURL:[NSURL URLWithString:@"https://thunder.highfidelity.com/builds/api/tags/latest?format=json"]]; [request setHTTPMethod:@"GET"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; - + // We're using an ephermeral session here to ensure the tags api response is never cached. NSURLSession * session = [NSURLSession sessionWithConfiguration:NSURLSessionConfiguration.ephemeralSessionConfiguration]; NSURLSessionDataTask* dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { - - NSLog(@"Latest Build Request error: %@", error); NSLog(@"Latest Build Request Data: %@", data); NSHTTPURLResponse *ne = (NSHTTPURLResponse *)response; NSLog(@"Latest Build Request Response: %ld", [ne statusCode]); Launcher* sharedLauncher = [Launcher sharedLauncher]; + + if ([ne statusCode] == 500) { + dispatch_async(dispatch_get_main_queue(), ^{ + [sharedLauncher displayErrorPage]; + }); + return; + } NSMutableData* webData = [NSMutableData data]; [webData appendData:data]; NSString* jsonString = [[NSString alloc] initWithBytes: [webData mutableBytes] length:[data length] encoding:NSUTF8StringEncoding]; @@ -46,25 +51,25 @@ NSLog(@"Latest Build Request -> json string: %@", jsonString); NSError *jsonError = nil; id json = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&jsonError]; - + if (jsonError) { NSLog(@"Latest Build request: Failed to convert Json to data"); } - + NSFileManager* fileManager = [NSFileManager defaultManager]; NSArray *values = [json valueForKey:@"results"]; NSDictionary *value = [values objectAtIndex:0]; - - + + NSString* buildNumber = [value valueForKey:@"latest_version"]; NSDictionary* installers = [value objectForKey:@"installers"]; NSDictionary* macInstallerObject = [installers objectForKey:@"mac"]; NSString* macInstallerUrl = [macInstallerObject valueForKey:@"zip_url"]; - + BOOL appDirectoryExist = [fileManager fileExistsAtPath:[[sharedLauncher getAppPath] stringByAppendingString:@"interface.app"]]; - + dispatch_async(dispatch_get_main_queue(), ^{ - + NSInteger currentVersion = [self getCurrentVersion]; NSLog(@"Latest Build Request -> does build directory exist: %@", appDirectoryExist ? @"TRUE" : @"FALSE"); NSLog(@"Latest Build Request -> current version: %ld", currentVersion); @@ -72,66 +77,13 @@ NSLog(@"Latest Build Request -> mac url: %@", macInstallerUrl); BOOL latestVersionAvailable = (currentVersion != buildNumber.integerValue); [[Settings sharedSettings] buildVersion:buildNumber.integerValue]; - + BOOL shouldDownloadInterface = (latestVersionAvailable || !appDirectoryExist); NSLog(@"Latest Build Request -> SHOULD DOWNLOAD: %@", shouldDownloadInterface ? @"TRUE" : @"FALSE"); [sharedLauncher shouldDownloadLatestBuild:shouldDownloadInterface :macInstallerUrl]; }); }]; - + [dataTask resume]; - - //NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; - - /*if(theConnection) { - self.webData = [NSMutableData data]; - NSLog(@"connection initiated"); - }*/ } - -- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { - [self.webData appendData:data]; -} - -- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { - NSHTTPURLResponse *ne = (NSHTTPURLResponse *)response; - if([ne statusCode] == 200) { - NSLog(@"connection state is 200 - all okay"); - } else { - NSLog(@"connection state is NOT 200"); - [[Launcher sharedLauncher] displayErrorPage]; - } -} - --(void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { - NSLog(@"Conn Err: %@", [error localizedDescription]); - [[Launcher sharedLauncher] displayErrorPage]; -} - -- (void)connectionDidFinishLoading:(NSURLConnection *)connection { - Launcher* sharedLauncher = [Launcher sharedLauncher]; - self.jsonString = [[NSString alloc] initWithBytes: [self.webData mutableBytes] length:[self.webData length] encoding:NSUTF8StringEncoding]; - NSData *data = [self.jsonString dataUsingEncoding:NSUTF8StringEncoding]; - id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; - - NSFileManager* fileManager = [NSFileManager defaultManager]; - NSArray *values = [json valueForKey:@"results"]; - NSDictionary *value = [values objectAtIndex:0]; - - - NSString* buildNumber = [value valueForKey:@"latest_version"]; - NSDictionary* installers = [value objectForKey:@"installers"]; - NSDictionary* macInstallerObject = [installers objectForKey:@"mac"]; - NSString* macInstallerUrl = [macInstallerObject valueForKey:@"zip_url"]; - - NSString* interfaceAppPath = [[sharedLauncher getAppPath] stringByAppendingString:@"interface.app"]; - BOOL appDirectoryExist = [fileManager fileExistsAtPath:interfaceAppPath]; - - BOOL latestVersionAvailable = ([self getCurrentVersion] != buildNumber.integerValue); - [[Settings sharedSettings] buildVersion:buildNumber.integerValue]; - - BOOL shouldDownloadInterface = (latestVersionAvailable || !appDirectoryExist); - [sharedLauncher shouldDownloadLatestBuild:shouldDownloadInterface :macInstallerUrl]; -} - @end diff --git a/launchers/darwin/src/Launcher.h b/launchers/darwin/src/Launcher.h index 69484a378d..de67850bfe 100644 --- a/launchers/darwin/src/Launcher.h +++ b/launchers/darwin/src/Launcher.h @@ -21,6 +21,12 @@ typedef enum LoginErrorTypes CREDENTIALS } LoginError; +struct LatestBuildInfo { + NSString* downloadURL; + BOOL shouldDownload; + BOOL requestBuildFinished; +}; + @interface Launcher : NSObject { } @property (nonatomic, retain) NSString* password; @@ -34,6 +40,7 @@ typedef enum LoginErrorTypes @property (nonatomic, retain) NSString* domainURL; @property (nonatomic, retain) NSString* domainContentUrl; @property (nonatomic, retain) NSString* domainScriptsUrl; +@property (nonatomic, retain) NSString* interfaceDownloadUrl; @property (nonatomic, retain) DownloadInterface* downloadInterface; @property (nonatomic, retain) CredentialsRequest* credentialsRequest; @property (nonatomic, retain) DownloadDomainContent* downloadDomainContent; @@ -44,9 +51,17 @@ typedef enum LoginErrorTypes @property (nonatomic) BOOL waitingForCredentialReponse; @property (nonatomic) BOOL gotCredentialResponse; @property (nonatomic) BOOL waitingForInterfaceToTerminate; +@property (nonatomic) BOOL shouldDownloadInterface; +@property (nonatomic) BOOL latestBuildRequestFinished; +@property (nonatomic, assign) NSTimer* updateProgressIndicatorTimer; @property (nonatomic, assign, readwrite) ProcessState processState; @property (nonatomic, assign, readwrite) LoginError loginError; +@property (nonatomic, assign) NSProgressIndicator* progressIndicator; +@property (nonatomic) double progressTarget; +@property (nonatomic) struct LatestBuildInfo buildInfo; +- (NSProgressIndicator*) getProgressView; +- (void) setProgressView:(NSProgressIndicator*) aProgressIndicator; - (void) displayNameEntered:(NSString*)aDisplayName; - (void) credentialsEntered:(NSString*)aOrginization :(NSString*)aUsername :(NSString*)aPassword; - (void) credentialsAccepted:(BOOL) aCredentialsAccepted; @@ -57,6 +72,7 @@ typedef enum LoginErrorTypes - (BOOL) loginShouldSetErrorState; - (void) displayErrorPage; - (void) showLoginScreen; +- (void) restart; - (NSString*) getLauncherPath; - (ProcessState) currentProccessState; - (void) setCurrentProcessState:(ProcessState) aProcessState; @@ -66,7 +82,7 @@ typedef enum LoginErrorTypes - (void) interfaceFinishedDownloading; - (NSString*) getDownloadPathForContentAndScripts; - (void) launchInterface; -- (void) extractZipFileAtDestination:(NSString*) destination :(NSString*) file; +- (BOOL) extractZipFileAtDestination:(NSString*) destination :(NSString*) file; - (BOOL) isWaitingForInterfaceToTerminate; - (void) setDownloadFilename:(NSString*) aFilename; - (void) setDownloadContextFilename:(NSString*) aFilename; @@ -76,8 +92,13 @@ typedef enum LoginErrorTypes - (NSString*) getDownloadContentFilename; - (NSString*) getDownloadScriptsFilename; - (NSString*) getDownloadFilename; +- (void) startUpdateProgressIndicatorTimer; +- (void) endUpdateProgressIndicatorTimer; - (BOOL) isLoadedIn; - (NSString*) getAppPath; +- (void) updateProgressIndicator; +- (void) setLatestBuildInfo:(struct LatestBuildInfo) latestBuildInfo; +- (struct LatestBuildInfo) getLatestBuildInfo; + (id) sharedLauncher; @end diff --git a/launchers/darwin/src/Launcher.m b/launchers/darwin/src/Launcher.m index d60c4080a2..1a84e9143d 100644 --- a/launchers/darwin/src/Launcher.m +++ b/launchers/darwin/src/Launcher.m @@ -17,6 +17,7 @@ static BOOL const DELETE_ZIP_FILES = TRUE; @implementation Launcher + + (id) sharedLauncher { static Launcher* sharedLauncher = nil; static dispatch_once_t onceToken; @@ -35,11 +36,18 @@ static BOOL const DELETE_ZIP_FILES = TRUE; self.latestBuildRequest = [LatestBuildRequest alloc]; self.organizationRequest = [OrganizationRequest alloc]; self.downloadScripts = [DownloadScripts alloc]; + struct LatestBuildInfo latestBuildInfo; + latestBuildInfo.downloadURL = nil; + latestBuildInfo.shouldDownload = FALSE; + latestBuildInfo.requestBuildFinished = FALSE; + self.buildInfo = latestBuildInfo; self.credentialsAccepted = TRUE; self.gotCredentialResponse = FALSE; self.waitingForCredentialReponse = FALSE; self.waitingForInterfaceToTerminate = FALSE; + self.latestBuildRequestFinished = FALSE; self.userToken = nil; + self.progressIndicator = nil; self.processState = DOWNLOADING_INTERFACE; } return self; @@ -51,11 +59,11 @@ static BOOL const DELETE_ZIP_FILES = TRUE; selector:@selector(didTerminateApp:) name:NSWorkspaceDidTerminateApplicationNotification object:nil]; - + SplashScreen* splashScreen = [[SplashScreen alloc] initWithNibName:@"SplashScreen" bundle:nil]; [self.window setContentViewController: splashScreen]; [self closeInterfaceIfRunning]; - + if (!self.waitingForInterfaceToTerminate) { [self checkLoginStatus]; } @@ -65,12 +73,12 @@ static BOOL const DELETE_ZIP_FILES = TRUE; { NSString* filePath = [[NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingString:@"/Launcher/"]; - + if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) { NSError * error = nil; [[NSFileManager defaultManager] createDirectoryAtPath:filePath withIntermediateDirectories:TRUE attributes:nil error:&error]; } - + return filePath; } @@ -79,19 +87,67 @@ static BOOL const DELETE_ZIP_FILES = TRUE; return [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/Contents/MacOS/"]; } -- (void) extractZipFileAtDestination:(NSString *)destination :(NSString*)file +- (void) updateProgressIndicator +{ + double contentPercentage = [self.downloadDomainContent getProgressPercentage]; + double interfacePercentage = [self.downloadInterface getProgressPercentage]; + double currentTotalPercentage = self.progressTarget; + if (self.processState == DOWNLOADING_INTERFACE) { + if (self.shouldDownloadInterface) { + currentTotalPercentage = (contentPercentage * 0.5) + (interfacePercentage * 0.5); + } else { + currentTotalPercentage = contentPercentage; + } + } else { + currentTotalPercentage = interfacePercentage; + } + self.progressTarget = currentTotalPercentage; +} + +- (double) lerp:(double) pointA :(double) pointB :(double) interp +{ + double lerpValue = pointA + interp * (pointB - pointA); + return lerpValue; +} + +- (BOOL) extractZipFileAtDestination:(NSString *)destination :(NSString*)file { NSTask* task = [[NSTask alloc] init]; task.launchPath = @"/usr/bin/unzip"; task.arguments = @[@"-o", @"-d", destination, file]; - + [task launch]; [task waitUntilExit]; - + if (DELETE_ZIP_FILES) { NSFileManager* fileManager = [NSFileManager defaultManager]; [fileManager removeItemAtPath:file error:NULL]; } + + if ([task terminationStatus] != 0) { + NSLog(@"Extracting file failed -> termination status: %d", [task terminationStatus]); + return FALSE; + } + + return TRUE; +} + +-(void) setProgressView:(NSProgressIndicator*) aProgressIndicator +{ + self.progressIndicator = aProgressIndicator; +} + +-(NSProgressIndicator*) getProgressView +{ + return self.progressIndicator; +} + +- (void) restart +{ + SplashScreen* splashScreen = [[SplashScreen alloc] initWithNibName:@"SplashScreen" bundle:nil]; + [[[[NSApplication sharedApplication] windows] objectAtIndex:0] setContentViewController: splashScreen]; + + [self checkLoginStatus]; } - (void) displayErrorPage @@ -102,19 +158,11 @@ static BOOL const DELETE_ZIP_FILES = TRUE; - (void) checkLoginStatus { - if ([self isLoadedIn]) { - Launcher* sharedLauncher = [Launcher sharedLauncher]; - [sharedLauncher setCurrentProcessState:CHECKING_UPDATE]; - ProcessScreen* processScreen = [[ProcessScreen alloc] initWithNibName:@"ProcessScreen" bundle:nil]; - [[[[NSApplication sharedApplication] windows] objectAtIndex:0] setContentViewController: processScreen]; - [self.latestBuildRequest requestLatestBuildInfo]; - } else { - [NSTimer scheduledTimerWithTimeInterval:2.0 - target:self - selector:@selector(onSplashScreenTimerFinished:) - userInfo:nil - repeats:NO]; - } + [NSTimer scheduledTimerWithTimeInterval:1.0 + target:self + selector:@selector(onSplashScreenTimerFinished:) + userInfo:nil + repeats:NO]; [[NSApplication sharedApplication] activateIgnoringOtherApps:TRUE]; } @@ -138,6 +186,31 @@ static BOOL const DELETE_ZIP_FILES = TRUE; return self.scriptsFilename; } +- (void) startUpdateProgressIndicatorTimer +{ + self.progressTarget = 0.0; + self.updateProgressIndicatorTimer = [NSTimer scheduledTimerWithTimeInterval: 0.0016 + target: self + selector: @selector(updateIndicator:) + userInfo:nil + repeats: YES]; + + [[NSRunLoop mainRunLoop] addTimer:self.updateProgressIndicatorTimer forMode:NSRunLoopCommonModes]; +} + +- (void) endUpdateProgressIndicatorTimer +{ + [self.updateProgressIndicatorTimer invalidate]; + self.updateProgressIndicatorTimer = nil; +} + +- (void) updateIndicator:(NSTimer*) timer +{ + NSProgressIndicator* progressIndicator = [self getProgressView]; + double oldValue = progressIndicator.doubleValue; + progressIndicator.doubleValue = [self lerp:oldValue :self.progressTarget :0.3]; +} + - (void)didTerminateApp:(NSNotification *)notification { if (self.waitingForInterfaceToTerminate) { NSString* appName = [notification.userInfo valueForKey:@"NSApplicationName"]; @@ -175,7 +248,7 @@ static BOOL const DELETE_ZIP_FILES = TRUE; self.domainURL = aDomainURL; self.domainContentUrl = aDomainContentUrl; self.domainScriptsUrl = aDomainScriptsUrl; - + [[Settings sharedSettings] setDomainUrl:aDomainURL]; } @@ -192,6 +265,7 @@ static BOOL const DELETE_ZIP_FILES = TRUE; - (void) displayNameEntered:(NSString*)aDiplayName { self.processState = DOWNLOADING_INTERFACE; + [self startUpdateProgressIndicatorTimer]; ProcessScreen* processScreen = [[ProcessScreen alloc] initWithNibName:@"ProcessScreen" bundle:nil]; [[[[NSApplication sharedApplication] windows] objectAtIndex:0] setContentViewController: processScreen]; [self.downloadDomainContent downloadDomainContent:self.domainContentUrl]; @@ -200,8 +274,11 @@ static BOOL const DELETE_ZIP_FILES = TRUE; - (void) domainContentDownloadFinished { - //.[self.downloadScripts downloadScripts:self.domainScriptsUrl]; - [self.latestBuildRequest requestLatestBuildInfo]; + if (self.shouldDownloadInterface) { + [self.downloadInterface downloadInterface: self.interfaceDownloadUrl]; + return; + } + [self interfaceFinishedDownloading]; } - (void) domainScriptsDownloadFinished @@ -228,14 +305,21 @@ static BOOL const DELETE_ZIP_FILES = TRUE; - (void) interfaceFinishedDownloading { - if (self.processState == DOWNLOADING_INTERFACE) { - self.processState = RUNNING_INTERFACE_AFTER_DOWNLOAD; + [self endUpdateProgressIndicatorTimer]; + NSProgressIndicator* progressIndicator = [self getProgressView]; + progressIndicator.doubleValue = self.progressTarget; + Launcher* sharedLauncher = [Launcher sharedLauncher]; + if ([sharedLauncher currentProccessState] == DOWNLOADING_INTERFACE) { + [sharedLauncher setCurrentProcessState: RUNNING_INTERFACE_AFTER_DOWNLOAD]; } else { - self.processState = RUNNING_INTERFACE_AFTER_UPDATE; + [sharedLauncher setCurrentProcessState: RUNNING_INTERFACE_AFTER_UPDATE]; } - ProcessScreen* processScreen = [[ProcessScreen alloc] initWithNibName:@"ProcessScreen" bundle:nil]; - [[[[NSApplication sharedApplication] windows] objectAtIndex:0] setContentViewController: processScreen]; - [self launchInterface]; + + [NSTimer scheduledTimerWithTimeInterval: 0.2 + target: self + selector: @selector(callLaunchInterface:) + userInfo:nil + repeats: NO]; } - (void) credentialsEntered:(NSString*)aOrginization :(NSString*)aUsername :(NSString*)aPassword @@ -262,6 +346,16 @@ static BOOL const DELETE_ZIP_FILES = TRUE; return YES; } +- (struct LatestBuildInfo) getLatestBuildInfo +{ + return self.buildInfo; +} + +- (void) setLatestBuildInfo:(struct LatestBuildInfo) latestBuildInfo +{ + self.buildInfo = latestBuildInfo; +} + -(void) showLoginScreen { LoginScreen* loginScreen = [[LoginScreen alloc] initWithNibName:@"LoginScreen" bundle:nil]; @@ -270,17 +364,29 @@ static BOOL const DELETE_ZIP_FILES = TRUE; - (void) shouldDownloadLatestBuild:(BOOL) shouldDownload :(NSString*) downloadUrl { - if (shouldDownload) { - [self.downloadInterface downloadInterface: downloadUrl]; - return; + self.shouldDownloadInterface = shouldDownload; + self.interfaceDownloadUrl = downloadUrl; + self.latestBuildRequestFinished = TRUE; + if ([self isLoadedIn]) { + Launcher* sharedLauncher = [Launcher sharedLauncher]; + [sharedLauncher setCurrentProcessState:CHECKING_UPDATE]; + if (shouldDownload) { + ProcessScreen* processScreen = [[ProcessScreen alloc] initWithNibName:@"ProcessScreen" bundle:nil]; + [[[[NSApplication sharedApplication] windows] objectAtIndex:0] setContentViewController: processScreen]; + [self startUpdateProgressIndicatorTimer]; + [self.downloadInterface downloadInterface: downloadUrl]; + return; + } + [self interfaceFinishedDownloading]; + } else { + [[NSApplication sharedApplication] activateIgnoringOtherApps:TRUE]; + [self showLoginScreen]; } - [self launchInterface]; } -(void)onSplashScreenTimerFinished:(NSTimer *)timer { - [[NSApplication sharedApplication] activateIgnoringOtherApps:TRUE]; - [self showLoginScreen]; + [self.latestBuildRequest requestLatestBuildInfo]; } -(void)setCurrentProcessState:(ProcessState)aProcessState @@ -326,17 +432,17 @@ static BOOL const DELETE_ZIP_FILES = TRUE; - (void) launchInterface { NSString* launcherPath = [[self getLauncherPath] stringByAppendingString:@"HQ Launcher"]; - + [[Settings sharedSettings] setLauncherPath:launcherPath]; [[Settings sharedSettings] save]; NSWorkspace *workspace = [NSWorkspace sharedWorkspace]; NSURL *url = [NSURL fileURLWithPath:[workspace fullPathForApplication:[[self getAppPath] stringByAppendingString:@"interface.app/Contents/MacOS/interface"]]]; NSError *error = nil; - + NSString* contentPath = [[self getDownloadPathForContentAndScripts] stringByAppendingString:@"content"]; NSString* displayName = [ self displayName]; - NSString* scriptsPath = [[self getAppPath] stringByAppendingString:@"interface.app/Contents/Resources/scripts/simplifiedUI/"]; + NSString* scriptsPath = [[self getAppPath] stringByAppendingString:@"interface.app/Contents/Resources/scripts/simplifiedUIBootstrapper.js"]; NSString* domainUrl = [[Settings sharedSettings] getDomainUrl]; NSString* userToken = [[Launcher sharedLauncher] getTokenString]; NSString* homeBookmark = [[NSString stringWithFormat:@"hqhome="] stringByAppendingString:domainUrl]; @@ -347,7 +453,7 @@ static BOOL const DELETE_ZIP_FILES = TRUE; @"--tokens", userToken, @"--cache", contentPath, @"--displayName", displayName, - @"--scripts", scriptsPath, + @"--defaultScriptsOverride", scriptsPath, @"--setBookmark", homeBookmark, @"--no-updater", @"--no-launcher", nil]; @@ -355,14 +461,18 @@ static BOOL const DELETE_ZIP_FILES = TRUE; arguments = [NSArray arrayWithObjects: @"--url" , domainUrl, @"--cache", contentPath, - @"--scripts", scriptsPath, + @"--defaultScriptsOverride", scriptsPath, @"--setBookmark", homeBookmark, @"--no-updater", @"--no-launcher", nil]; } [workspace launchApplicationAtURL:url options:NSWorkspaceLaunchNewInstance configuration:[NSDictionary dictionaryWithObject:arguments forKey:NSWorkspaceLaunchConfigurationArguments] error:&error]; - - [NSApp terminate:self]; + + [NSTimer scheduledTimerWithTimeInterval: 3.0 + target: self + selector: @selector(exitLauncher:) + userInfo:nil + repeats: NO]; } - (ProcessState) currentProccessState @@ -370,4 +480,17 @@ static BOOL const DELETE_ZIP_FILES = TRUE; return self.processState; } +- (void) callLaunchInterface:(NSTimer*) timer +{ + ProcessScreen* processScreen = [[ProcessScreen alloc] initWithNibName:@"ProcessScreen" bundle:nil]; + [[[[NSApplication sharedApplication] windows] objectAtIndex:0] setContentViewController: processScreen]; + [self launchInterface]; +} + + +- (void) exitLauncher:(NSTimer*) timer +{ + [NSApp terminate:self]; +} + @end diff --git a/launchers/darwin/src/LoginScreen.m b/launchers/darwin/src/LoginScreen.m index 4c83558160..d654a14f1b 100644 --- a/launchers/darwin/src/LoginScreen.m +++ b/launchers/darwin/src/LoginScreen.m @@ -38,25 +38,25 @@ [self.backgroundImage setImage:[NSImage imageNamed:hifiBackgroundFilename]]; [self.smallLogo setImage:[NSImage imageNamed:hifiSmallLogoFilename]]; - + NSMutableAttributedString* usernameString = [[NSMutableAttributedString alloc] initWithString:@"Username"]; - + [usernameString addAttribute:NSForegroundColorAttributeName value:[NSColor grayColor] range:NSMakeRange(0,8)]; [usernameString addAttribute:NSFontAttributeName value:[NSFont systemFontOfSize:18] range:NSMakeRange(0,8)]; - + NSMutableAttributedString* orgName = [[NSMutableAttributedString alloc] initWithString:@"Organization Name"]; [orgName addAttribute:NSForegroundColorAttributeName value:[NSColor grayColor] range:NSMakeRange(0,17)]; [orgName addAttribute:NSFontAttributeName value:[NSFont systemFontOfSize:18] range:NSMakeRange(0,17)]; - + NSMutableAttributedString* passwordString = [[NSMutableAttributedString alloc] initWithString:@"Password"]; - + [passwordString addAttribute:NSForegroundColorAttributeName value:[NSColor grayColor] range:NSMakeRange(0,8)]; [passwordString addAttribute:NSFontAttributeName value:[NSFont systemFontOfSize:18] range:NSMakeRange(0,8)]; - + [self.username setPlaceholderAttributedString:usernameString]; [self.orginization setPlaceholderAttributedString:orgName]; [self.password setPlaceholderAttributedString:passwordString]; - + [self.password setTarget:self]; [self.password setAction:@selector(goToLogin:)]; } diff --git a/launchers/darwin/src/OrganizationRequest.h b/launchers/darwin/src/OrganizationRequest.h index 2f7d2570d6..e10719c332 100644 --- a/launchers/darwin/src/OrganizationRequest.h +++ b/launchers/darwin/src/OrganizationRequest.h @@ -1,6 +1,6 @@ #import -@interface OrganizationRequest : NSObject { +@interface OrganizationRequest : NSObject { } @property (nonatomic, retain) NSMutableData* webData; diff --git a/launchers/darwin/src/OrganizationRequest.m b/launchers/darwin/src/OrganizationRequest.m index abc104785a..1aaed2ce51 100644 --- a/launchers/darwin/src/OrganizationRequest.m +++ b/launchers/darwin/src/OrganizationRequest.m @@ -6,6 +6,11 @@ static NSString* const organizationURL = @"https://orgs.highfidelity.com/organizations/"; +@interface OrganizationRequest () +@property (nonatomic, assign) NSMutableData* receivedData; +@property (nonatomic, assign) NSInteger statusCode; +@end + @implementation OrganizationRequest - (void) confirmOrganization:(NSString*)aOrganization :(NSString*)aUsername { @@ -23,70 +28,72 @@ static NSString* const organizationURL = @"https://orgs.highfidelity.com/organiz } NSString* jsonFile = [hash stringByAppendingString:@".json"]; - NSError *error; - NSData *data = [NSData dataWithContentsOfURL: [NSURL URLWithString:[organizationURL stringByAppendingString:jsonFile]]]; - - Launcher* sharedLauncher = [Launcher sharedLauncher]; - if (data) { - NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error]; - [sharedLauncher setDomainURLInfo:[json valueForKey:@"domain"] :[json valueForKey:@"content_set_url"] :[json valueForKey:@"scripts_url"]]; - [sharedLauncher setLoginErrorState: NONE]; - return [sharedLauncher organizationRequestFinished:TRUE]; - } - [sharedLauncher setLoginErrorState: ORGANIZATION]; - return [sharedLauncher organizationRequestFinished:FALSE]; - /*NSLog(@"URL: %@", [organizationURL stringByAppendingString:jsonFile]); + NSMutableURLRequest *request = [NSMutableURLRequest new]; - [request setURL:[NSURL URLWithString: [organizationURL stringByAppendingString:@"High%20Fidelity"]]]; + [request setURL:[NSURL URLWithString:[organizationURL stringByAppendingString:jsonFile]]]; [request setHTTPMethod:@"GET"]; - [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; + [request setValue:@"" forHTTPHeaderField:@"Content-Type"]; - NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; - - if(theConnection) { - self.webData = [NSMutableData data]; - NSLog(@"connection initiated"); - }*/ + NSURLSession * session = [NSURLSession sessionWithConfiguration:NSURLSessionConfiguration.ephemeralSessionConfiguration delegate: self delegateQueue: [NSOperationQueue mainQueue]]; + NSURLSessionDataTask* dataTask = [session dataTaskWithRequest:request]; + [dataTask resume]; } -- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { - [self.webData appendData:data]; -} -- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { +- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response + completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler { + self.receivedData = nil; + self.receivedData = [[NSMutableData alloc] init]; + [self.receivedData setLength:0]; NSHTTPURLResponse *ne = (NSHTTPURLResponse *)response; - if([ne statusCode] == 200) { - NSLog(@"connection state is 200 - all okay"); + self.statusCode = [ne statusCode]; + NSLog(@"Organization Response status code: %ld", self.statusCode); + completionHandler(NSURLSessionResponseAllow); +} + + +-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask + didReceiveData:(NSData *)data { + + [self.receivedData appendData:data]; + NSLog(@"Organization: did recieve data"); +} + +- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { + Launcher* sharedLauncher = [Launcher sharedLauncher]; + if (error) { + NSLog(@"Organization: Request completed with an error -> error: %@", error); + [sharedLauncher displayErrorPage]; } else { - NSLog(@"connection state is NOT 200"); + if (self.statusCode == 200) { + NSError *jsonError = nil; + NSDictionary *json = [NSJSONSerialization JSONObjectWithData:self.receivedData options:kNilOptions error:&jsonError]; + if (jsonError) { + NSLog(@"Failed to parse Organzation json -> error: %@", jsonError); + [sharedLauncher displayErrorPage]; + return; + } + NSString* domainURL = [json valueForKey:@"domain"]; + NSString* contentSetURL = [json valueForKey:@"content_set_url"]; + + if (domainURL != nil && contentSetURL != nil) { + NSLog(@"Organization: getting org file successful"); + [sharedLauncher setDomainURLInfo:[json valueForKey:@"domain"] :[json valueForKey:@"content_set_url"] :nil]; + [sharedLauncher setLoginErrorState: NONE]; + [sharedLauncher organizationRequestFinished:TRUE]; + } else { + NSLog(@"Organization: Either domainURL: %@ or contentSetURL: %@ json entries are invalid", domainURL, contentSetURL); + [sharedLauncher displayErrorPage]; + } + } else if (self.statusCode == 403 || self.statusCode == 404) { + NSLog(@"Organization: failed to get org file"); + [sharedLauncher setLoginErrorState: ORGANIZATION]; + [sharedLauncher organizationRequestFinished:FALSE]; + } else { + NSLog(@ "Organization: Response error -> statusCode: %ld", self.statusCode); + [sharedLauncher displayErrorPage]; + } } } --(void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { - NSLog(@"Conn Err: %@", [error localizedDescription]); -} - -- (void)connectionDidFinishLoading:(NSURLConnection *)connection { - /*NSString* jsonString = [[NSString alloc] initWithBytes: [self.webData mutableBytes] length:[self.webData length] encoding:NSUTF8StringEncoding]; - NSData *data = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; - id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];*/ - - /*Launcher* sharedLauncher = [Launcher sharedLauncher]; - if (json[@"error"] != nil) { - NSLog(@"Login in failed"); - NSString* accessToken = [json objectForKey:@"access_token"]; - NSLog(@"access token %@", accessToken); - [sharedLauncher credentialsAccepted:FALSE]; - } else { - NSLog(@"Login successful"); - NSString* accessToken = [json objectForKey:@"access_token"]; - NSLog(@"access token %@", accessToken); - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - [defaults setValue:accessToken forKey:@"access_token"]; - [defaults synchronize]; - [sharedLauncher credentialsAccepted:TRUE]; - }*/ - //NSLog(@"OUTPUT:: %@", self.jsonString); -} - @end diff --git a/launchers/darwin/src/ProcessScreen.m b/launchers/darwin/src/ProcessScreen.m index 4aeb8abda1..85ec5c8d5b 100644 --- a/launchers/darwin/src/ProcessScreen.m +++ b/launchers/darwin/src/ProcessScreen.m @@ -8,6 +8,7 @@ @property (nonatomic, assign) IBOutlet NSImageView* voxelImage; @property (nonatomic, assign) IBOutlet NSTextField* boldStatus; @property (nonatomic, assign) IBOutlet NSTextField* smallStatus; +@property (nonatomic, assign) IBOutlet NSProgressIndicator* progressView; @end @implementation ProcessScreen @@ -20,6 +21,7 @@ [self.smallStatus setStringValue:@"Set up may take several minutes."]; break; case RUNNING_INTERFACE_AFTER_DOWNLOAD: + [self.progressView setHidden: YES]; [self.boldStatus setStringValue:@"Your new HQ is all setup"]; [self.smallStatus setStringValue:@"Thanks for being patient."]; break; @@ -28,6 +30,7 @@ [self.smallStatus setStringValue:@"We're getting the latest and greatest for you, one sec."]; break; case RUNNING_INTERFACE_AFTER_UPDATE: + [self.progressView setHidden: YES]; [self.boldStatus setStringValue:@"You're good to go!"]; [self.smallStatus setStringValue:@"Thanks for being patient."]; break; @@ -37,10 +40,11 @@ [self.background setImage: [NSImage imageNamed:hifiBackgroundFilename]]; [self.smallLogo setImage: [NSImage imageNamed:hifiSmallLogoFilename]]; [self.voxelImage setImage: [NSImage imageNamed:hifiVoxelFilename]]; + if (self.progressView != nil) { + [sharedLauncher setProgressView: self.progressView]; + } self.imageRotation = 0; - //[self.voxelImage setFrameCenterRotation:90]; - [NSTimer scheduledTimerWithTimeInterval:0.016 target:self selector:@selector(rotateView:) diff --git a/launchers/darwin/src/Window.h b/launchers/darwin/src/Window.h index 05e1a7e09e..ace35baab6 100644 --- a/launchers/darwin/src/Window.h +++ b/launchers/darwin/src/Window.h @@ -1,6 +1,6 @@ #import @interface Window : NSWindow { - + } @end diff --git a/launchers/darwin/src/Window.m b/launchers/darwin/src/Window.m index fc54e095e7..a17b2533fd 100644 --- a/launchers/darwin/src/Window.m +++ b/launchers/darwin/src/Window.m @@ -4,4 +4,10 @@ -(BOOL)canBecomeKeyWindow { return YES; } + +-(BOOL)isMovableByWindowBackground +{ + return TRUE; +} + @end diff --git a/launchers/win32/Launcher.rc b/launchers/win32/Launcher.rc index 4d9e0ffcd6..eb72dced4c 100644 --- a/launchers/win32/Launcher.rc +++ b/launchers/win32/Launcher.rc @@ -21,6 +21,7 @@ #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// @@ -91,7 +92,8 @@ STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION EXSTYLE WS_EX_APPWINDOW FONT 10, "MS Shell Dlg", 400, 0, 0x0 BEGIN - CONTROL "",IDC_VOXEL,"Static",SS_BLACKRECT,65,27,174,123 + CONTROL "",IDC_VOXEL,"Static",SS_BLACKRECT,65,3,174,123, NOT WS_VISIBLE + CONTROL "", IDC_PROGRESS, "Static", SS_BLACKRECT, 35, 170, 239, 4, NOT WS_VISIBLE EDITTEXT IDC_ORGNAME,44,68,219,12,ES_AUTOHSCROLL | NOT WS_VISIBLE | NOT WS_BORDER EDITTEXT IDC_USERNAME,44,95,219,12,ES_AUTOHSCROLL | NOT WS_VISIBLE | NOT WS_BORDER EDITTEXT IDC_PASSWORD,44,122,219,12,ES_PASSWORD | ES_AUTOHSCROLL | NOT WS_VISIBLE | NOT WS_BORDER @@ -100,10 +102,10 @@ BEGIN LTEXT "Password",IDC_PASSWORD_BANNER,48,122,219,12,NOT WS_VISIBLE CTEXT "",IDC_MESSAGE_LABEL,5,39,299,23,NOT WS_VISIBLE CTEXT "",IDC_ACTION_LABEL,10,15,286,25,NOT WS_VISIBLE - CTEXT "",IDC_MESSAGE2_LABEL,35,172,239,15,NOT WS_VISIBLE - CTEXT "",IDC_ACTION2_LABEL,15,147,278,25,NOT WS_VISIBLE + CTEXT "",IDC_MESSAGE2_LABEL,35,148,239,15,NOT WS_VISIBLE + CTEXT "",IDC_ACTION2_LABEL,15,123,278,25,NOT WS_VISIBLE RTEXT "",IDC_TERMS,15,172,180,15,NOT WS_VISIBLE - CONTROL "",IDC_TERMS_LINK,"Button", BS_OWNERDRAW | BS_FLAT | NOT WS_VISIBLE | WS_TABSTOP,197,172,80,15 + CONTROL "",IDC_TERMS_LINK,"Button",BS_OWNERDRAW | BS_FLAT | NOT WS_VISIBLE | WS_TABSTOP,197,172,80,15 CTEXT "",IDC_TROUBLE,65,203,174,15,NOT WS_VISIBLE CONTROL "NEXT",IDC_BUTTON_NEXT,"Button",BS_OWNERDRAW | BS_FLAT | NOT WS_VISIBLE | WS_TABSTOP,107,158,94,16 CONTROL "Having Trouble?",IDC_TROUBLE_LINK,"Button",BS_OWNERDRAW | BS_FLAT | NOT WS_VISIBLE | WS_TABSTOP,126,203,56,11 diff --git a/launchers/win32/LauncherApp.cpp b/launchers/win32/LauncherApp.cpp index 4ed20fea13..c15ba75a9b 100644 --- a/launchers/win32/LauncherApp.cpp +++ b/launchers/win32/LauncherApp.cpp @@ -32,19 +32,36 @@ CLauncherApp theApp; // CLauncherApp initialization BOOL CLauncherApp::InitInstance() { - // don't launch if already running - CreateMutex(NULL, TRUE, _T("HQ_Launcher_Mutex")); - if (GetLastError() == ERROR_ALREADY_EXISTS) { - return FALSE; + // Close interface if is running + int interfacePID = -1; + if (LauncherUtils::isProcessRunning(L"interface.exe", interfacePID)) { + LauncherUtils::shutdownProcess(interfacePID, 0); } int iNumOfArgs; LPWSTR* pArgs = CommandLineToArgvW(GetCommandLine(), &iNumOfArgs); - if (iNumOfArgs > 1 && CString(pArgs[1]).Compare(_T("--uninstall")) == 0) { + bool isUninstalling = false; + bool isRestarting = false; + if (iNumOfArgs > 1) { + if (CString(pArgs[1]).Compare(_T("--uninstall")) == 0) { + isUninstalling = true; + } else if (CString(pArgs[1]).Compare(_T("--restart")) == 0) { + isRestarting = true; + } + } + if (!isRestarting) { + // don't launch if already running + CreateMutex(NULL, TRUE, _T("HQ_Launcher_Mutex")); + if (GetLastError() == ERROR_ALREADY_EXISTS) { + return FALSE; + } + } + + if (isUninstalling) { _manager.uninstall(); } else { _manager.init(); } - if (!_manager.installLauncher()) { + if (!_manager.hasFailed() && !_manager.installLauncher()) { return FALSE; } installFont(IDR_FONT_REGULAR); diff --git a/launchers/win32/LauncherDlg.cpp b/launchers/win32/LauncherDlg.cpp index a4fe9e494b..704a2f3050 100644 --- a/launchers/win32/LauncherDlg.cpp +++ b/launchers/win32/LauncherDlg.cpp @@ -9,6 +9,7 @@ // #include "stdafx.h" +#include #include "LauncherApp.h" #include "LauncherDlg.h" @@ -109,8 +110,10 @@ BOOL CLauncherDlg::OnInitDialog() { m_trouble = (CStatic *)GetDlgItem(IDC_TROUBLE); m_voxel = (CStatic *)GetDlgItem(IDC_VOXEL); + m_progress = (CStatic *)GetDlgItem(IDC_PROGRESS); m_voxel->EnableD2DSupport(); + m_progress->EnableD2DSupport(); m_pRenderTarget = GetRenderTarget(); @@ -119,22 +122,58 @@ BOOL CLauncherDlg::OnInitDialog() { return TRUE; } +POINT CLauncherDlg::getMouseCoords(MSG* pMsg) { + POINT pos; + pos.x = (int)(short)LOWORD(pMsg->lParam); + pos.y = (int)(short)HIWORD(pMsg->lParam); + return pos; +} + BOOL CLauncherDlg::PreTranslateMessage(MSG* pMsg) { - if ((pMsg->message == WM_KEYDOWN)) - { + switch (pMsg->message) { + case WM_KEYDOWN: if (pMsg->wParam == 'A' && GetKeyState(VK_CONTROL) < 0) { CWnd* wnd = GetFocus(); CWnd* myWnd = this->GetDlgItem(IDC_ORGNAME); if (wnd && (wnd == this->GetDlgItem(IDC_ORGNAME) || - wnd == this->GetDlgItem(IDC_USERNAME) || - wnd == this->GetDlgItem(IDC_PASSWORD))) { + wnd == this->GetDlgItem(IDC_USERNAME) || + wnd == this->GetDlgItem(IDC_PASSWORD))) { ((CEdit*)wnd)->SetSel(0, -1); } return TRUE; } else if (pMsg->wParam == VK_RETURN) { OnNextClicked(); return TRUE; + } else if (pMsg->wParam == VK_ESCAPE) { + theApp._manager.onCancel(); } + break; + case WM_LBUTTONDOWN: + if (pMsg->hwnd == GetSafeHwnd()) { + _draggingWindow = true; + _dragOffset = getMouseCoords(pMsg); + SetCapture(); + } + break; + case WM_LBUTTONUP: + if (_draggingWindow) { + ReleaseCapture(); + _draggingWindow = false; + } + break; + case WM_MOUSEMOVE: + if (_draggingWindow) { + POINT pos = getMouseCoords(pMsg); + RECT windowRect; + GetWindowRect(&windowRect); + int width = windowRect.right - windowRect.left; + int height = windowRect.bottom - windowRect.top; + ClientToScreen(&pos); + MoveWindow(pos.x - _dragOffset.x, pos.y - _dragOffset.y, width, height, FALSE); + } + break; + default: + break; } return CDialog::PreTranslateMessage(pMsg); } @@ -174,19 +213,11 @@ void CLauncherDlg::startProcess() { theApp._manager.addToLog(_T("Starting Process Setup")); setDrawDialog(DrawStep::DrawProcessSetup); } - theApp._manager.addToLog(_T("Deleting directories before install")); - - CString installDir; - theApp._manager.getAndCreatePaths(LauncherManager::PathType::Interface_Directory, installDir); + theApp._manager.addToLog(_T("Deleting download directory")); CString downloadDir; theApp._manager.getAndCreatePaths(LauncherManager::PathType::Download_Directory, downloadDir); - - LauncherUtils::deleteDirectoriesOnThread(installDir, downloadDir, [&](int error) { - LauncherUtils::DeleteDirError deleteError = (LauncherUtils::DeleteDirError)error; - switch(error) { - case LauncherUtils::DeleteDirError::NoErrorDeleting: - theApp._manager.addToLog(_T("Install directory deleted.")); - theApp._manager.addToLog(_T("Downloads directory deleted.")); + LauncherUtils::deleteDirectoryOnThread(downloadDir, [&](bool error) { + if (!error) { if (!theApp._manager.isLoggedIn()) { theApp._manager.addToLog(_T("Downloading Content")); theApp._manager.downloadContent(); @@ -194,20 +225,12 @@ void CLauncherDlg::startProcess() { theApp._manager.addToLog(_T("Downloading App")); theApp._manager.downloadApplication(); } - break; - case LauncherUtils::DeleteDirError::ErrorDeletingBothDirs: - theApp._manager.addToLog(_T("Error deleting directories.")); - break; - case LauncherUtils::DeleteDirError::ErrorDeletingApplicationDir: - theApp._manager.addToLog(_T("Error deleting application directory.")); - break; - case LauncherUtils::DeleteDirError::ErrorDeletingDownloadsDir: - theApp._manager.addToLog(_T("Error deleting downloads directory.")); - break; - default: - break; + } else { + theApp._manager.addToLog(_T("Error deleting download directory.")); + theApp._manager.setFailed(true); } }); + } BOOL CLauncherDlg::getHQInfo(const CString& orgname) { @@ -230,13 +253,26 @@ afx_msg void CLauncherDlg::OnTermsClicked() { } afx_msg void CLauncherDlg::OnNextClicked() { - if (_drawStep != DrawStep::DrawChoose) { + if (_drawStep == DrawStep::DrawChoose) { + CString displayName; + m_username.GetWindowTextW(displayName); + theApp._manager.setDisplayName(displayName); + theApp._manager.addToLog(_T("Setting display name: " + displayName)); + startProcess(); + } else if (_drawStep == DrawStep::DrawError) { + theApp._manager.restartLauncher(); + } else if (_drawStep == DrawStep::DrawLoginLogin || + _drawStep == DrawStep::DrawLoginErrorCred || + _drawStep == DrawStep::DrawLoginErrorOrg) { CString token; CString username, password, orgname; m_orgname.GetWindowTextW(orgname); m_username.GetWindowTextW(username); m_password.GetWindowTextW(password); - + // trim spaces + orgname = CString(std::regex_replace(LauncherUtils::cStringToStd(orgname), std::regex("^ +| +$|( ) +"), "$1").c_str()); + username = CString(std::regex_replace(LauncherUtils::cStringToStd(username), std::regex("^ +| +$|( ) +"), "$1").c_str()); + // encode username = LauncherUtils::urlEncodeString(username); password = LauncherUtils::urlEncodeString(password); LauncherUtils::ResponseError error; @@ -261,19 +297,14 @@ afx_msg void CLauncherDlg::OnNextClicked() { setDrawDialog(DrawStep::DrawLoginErrorOrg); } } - } else { - CString displayName; - m_username.GetWindowTextW(displayName); - theApp._manager.setDisplayName(displayName); - theApp._manager.addToLog(_T("Setting display name: " + displayName)); - startProcess(); } } void CLauncherDlg::drawBackground(CHwndRenderTarget* pRenderTarget) { CD2DBitmap m_pBitmamBackground(pRenderTarget, IDB_PNG1, _T("PNG")); - auto size = pRenderTarget->GetSize(); + auto size = GetRenderTarget()->GetSize(); CD2DRectF backRec(0.0f, 0.0f, size.width, size.height); + GetRenderTarget()->DrawBitmap(&m_pBitmamBackground, backRec); pRenderTarget->DrawBitmap(&m_pBitmamBackground, backRec); } @@ -283,7 +314,7 @@ void CLauncherDlg::drawLogo(CHwndRenderTarget* pRenderTarget) { int logoWidth = 231; int logoHeight = 173; float logoPosX = 0.5f * (size.width - logoWidth); - float logoPosY = 0.95f * (size.height - logoHeight); + float logoPosY = 0.5f * (size.height - logoHeight); CD2DRectF logoRec(logoPosX, logoPosY, logoPosX + logoWidth, logoPosY + logoHeight); pRenderTarget->DrawBitmap(&m_pBitmamLogo, logoRec); } @@ -318,6 +349,27 @@ void CLauncherDlg::drawVoxel(CHwndRenderTarget* pRenderTarget) { pRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity()); } +void CLauncherDlg::drawProgress(CHwndRenderTarget* pRenderTarget, float progress, const D2D1::ColorF& color) { + auto size = pRenderTarget->GetPixelSize(); + if (progress == 0.0f) { + return; + } else { + progress = min(1.0f, progress); + } + CRect winRec; + float fullHeight = (float)size.height; + float halfHeight = 0.5f * (float)size.height; + CD2DRectF bkCircleRect1 = CD2DRectF(0.0f, 0.0f, fullHeight, fullHeight); + float progPos = halfHeight + (float)(size.width - size.height) * progress; + CD2DRectF bkCircleRect2 = CD2DRectF(progPos - halfHeight, 0.0f, progPos + halfHeight, fullHeight); + CD2DRectF bkRect = CD2DRectF(halfHeight, 0.0f, progPos, fullHeight); + CD2DEllipse bkCircle1 = CD2DEllipse(bkCircleRect1); + CD2DEllipse bkCircle2 = CD2DEllipse(bkCircleRect2); + CD2DSolidColorBrush brush(pRenderTarget, color); + pRenderTarget->FillEllipse(bkCircle1, &brush); + pRenderTarget->FillEllipse(bkCircle2, &brush); + pRenderTarget->FillRectangle(bkRect, &brush); +} void CLauncherDlg::showWindows(std::vector windows, bool show) { for (auto window : windows) { @@ -327,6 +379,7 @@ void CLauncherDlg::showWindows(std::vector windows, bool show) { void CLauncherDlg::prepareLogin(DrawStep step) { m_voxel->ShowWindow(SW_HIDE); + m_progress->ShowWindow(SW_HIDE); m_orgname_banner->SetWindowTextW(_T("Organization Name")); m_username_banner->SetWindowTextW(_T("Username")); m_password_banner->SetWindowTextW(_T("Password")); @@ -342,7 +395,7 @@ void CLauncherDlg::prepareLogin(DrawStep step) { m_password.ShowWindow(SW_SHOW); CString actionText = step == DrawStep::DrawLoginLogin ? _T("Please log in") : _T("Uh-oh, we have a problem"); CString messageText = step == DrawStep::DrawLoginLogin ? _T("Be sure you've uploaded your Avatar before signing in.") : - step == DrawStep::DrawLoginErrorCred ? _T("There is a problem with your credentials\n please try again.") : _T("There is a problem with your Organization name\n please try again."); + step == DrawStep::DrawLoginErrorCred ? _T("There is a problem with your credentials.\n Please try again.") : _T("There is a problem with your Organization name.\n Please try again."); m_action_label->SetWindowTextW(actionText); m_message_label->SetWindowTextW(messageText); m_action_label->ShowWindow(SW_SHOW); @@ -351,10 +404,8 @@ void CLauncherDlg::prepareLogin(DrawStep step) { m_trouble->SetWindowTextW(_T("Having Trouble?")); m_trouble->ShowWindow(SW_SHOW); m_trouble_link.ShowWindow(SW_SHOW); - } - void CLauncherDlg::prepareChoose() { m_orgname.ShowWindow(SW_HIDE); m_username.SetWindowTextW(_T("")); @@ -371,14 +422,7 @@ void CLauncherDlg::prepareChoose() { m_terms_link.ShowWindow(SW_SHOW); m_terms->SetWindowTextW(_T("By signing in, you agree to the High Fidelity")); m_terms_link.SetWindowTextW(_T("Terms of Service")); - CRect rec; - m_btnNext.GetWindowRect(&rec); - ScreenToClient(&rec); - if (rec.top > 281) { - rec.bottom -= 35; - rec.top -= 35; - m_btnNext.MoveWindow(rec, FALSE); - } + setVerticalElement(&m_btnNext, -35, 0, false); m_btnNext.ShowWindow(SW_SHOW); } @@ -399,8 +443,10 @@ void CLauncherDlg::prepareProcess(DrawStep step) { m_action_label->ShowWindow(SW_HIDE); m_message_label->ShowWindow(SW_HIDE); m_voxel->ShowWindow(SW_SHOW); + m_progress->ShowWindow(SW_SHOW); CString actionText = _T(""); CString messageText = _T(""); + switch (step) { case DrawStep::DrawProcessSetup: actionText = _T("We're building your virtual HQ"); @@ -422,6 +468,16 @@ void CLauncherDlg::prepareProcess(DrawStep step) { actionText = _T("Uninstalling..."); messageText = _T("It'll take one sec."); break; + case DrawStep::DrawError: + actionText = _T("Uh oh."); + messageText = _T("We seem to have a problem.\nPlease restart HQ."); + setVerticalElement(m_message2_label, 0, 5, false); + setVerticalElement(&m_btnNext, 10); + m_btnNext.ShowWindow(SW_SHOW); + m_progress->ShowWindow(SW_HIDE); + break; + default: + break; } m_action2_label->SetWindowTextW(actionText); m_message2_label->SetWindowTextW(messageText); @@ -429,9 +485,6 @@ void CLauncherDlg::prepareProcess(DrawStep step) { m_message2_label->ShowWindow(SW_SHOW); } -void CLauncherDlg::prepareError() { -} - BOOL CLauncherDlg::getTextFormat(int resID, TextFormat& formatOut) { // Set default values for message BOOL isText = TRUE; @@ -485,7 +538,6 @@ BOOL CLauncherDlg::getTextFormat(int resID, TextFormat& formatOut) { HBRUSH CLauncherDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { - HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor); TextFormat textFormat; int resId = pWnd->GetDlgCtrlID(); @@ -505,6 +557,7 @@ HBRUSH CLauncherDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) CRect lineRect = CRect(rect.left + padding, rect.bottom, rect.right - padding, rect.bottom + borderThick); lineRect.MoveToY(lineRect.bottom + 1); pDC->FillSolidRect(lineRect, COLOR_GREY); + } } return (HBRUSH)GetStockObject(BLACK_BRUSH); @@ -523,6 +576,8 @@ void CLauncherDlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) btnName += _drawStep == DrawStep::DrawLoginLogin ? _T("NEXT") : _T("LOG IN"); int xpan = -20; defrect = CRect(rect.left - xpan, rect.top, rect.right + xpan, rect.bottom); + } else if (_drawStep == DrawStep::DrawError) { + btnName += _T("RESTART"); } else { btnName += _T("TRY AGAIN"); } @@ -592,66 +647,105 @@ BOOL CLauncherDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) } void CLauncherDlg::OnTimer(UINT_PTR nIDEvent) { - const int CONSOLE_MAX_SHUTDOWN_TRY_COUNT = 10; - const int CONSOLE_DELTATIME_BETWEEN_TRYS = 10; - if (_drawStep == DrawStep::DrawProcessSetup || - _drawStep == DrawStep::DrawProcessUpdate || - _drawStep == DrawStep::DrawProcessUninstall) { - // Refresh - setDrawDialog(_drawStep, true); + + + if (theApp._manager.hasFailed() && _drawStep != DrawStep::DrawError) { + theApp._manager.saveErrorLog(); + prepareProcess(DrawStep::DrawError); + setDrawDialog(DrawStep::DrawError, false); } - if (_showSplash) { - if (_splashStep == 0){ - if (theApp._manager.needsUninstall()) { - theApp._manager.addToLog(_T("Waiting to uninstall")); - setDrawDialog(DrawStep::DrawProcessUninstall); - } else { - theApp._manager.addToLog(_T("Start splash screen")); - setDrawDialog(DrawStep::DrawLogo); - } - } else if (_splashStep > 100) { - _showSplash = false; - if (theApp._manager.shouldShutDown()) { - if (_applicationWND != NULL) { - ::SetForegroundWindow(_applicationWND); - ::SetActiveWindow(_applicationWND); + if (_drawStep != DrawStep::DrawError) { + if (_drawStep == DrawStep::DrawProcessSetup || + _drawStep == DrawStep::DrawProcessUpdate || + _drawStep == DrawStep::DrawProcessUninstall || + _drawStep == DrawStep::DrawProcessFinishHq || + _drawStep == DrawStep::DrawProcessFinishUpdate) { + // Refresh + setDrawDialog(_drawStep, true); + } + if (_showSplash) { + if (_splashStep == 0) { + if (theApp._manager.needsUninstall()) { + theApp._manager.addToLog(_T("Waiting to uninstall")); + setDrawDialog(DrawStep::DrawProcessUninstall); + } else { + theApp._manager.addToLog(_T("Start splash screen")); + setDrawDialog(DrawStep::DrawLogo); } - if (LauncherUtils::IsProcessRunning(L"interface.exe")) { - exit(0); + } else if (_splashStep > 100) { + _showSplash = false; + if (theApp._manager.shouldShutDown()) { + if (_applicationWND != NULL) { + ::SetForegroundWindow(_applicationWND); + ::SetActiveWindow(_applicationWND); + } + if (LauncherUtils::isProcessWindowOpened(L"interface.exe")) { + exit(0); + } + } else if (theApp._manager.needsUpdate()) { + startProcess(); + } else if (theApp._manager.needsUninstall()) { + if (theApp._manager.uninstallApplication()) { + theApp._manager.addToLog(_T("HQ uninstalled successfully.")); + exit(0); + } else { + theApp._manager.addToLog(_T("HQ failed to uninstall.")); + theApp._manager.setFailed(true); + } + } else { + theApp._manager.addToLog(_T("Starting login")); + setDrawDialog(DrawStep::DrawLoginLogin); } - } else if (theApp._manager.needsUpdate()) { - startProcess(); } else if (theApp._manager.needsUninstall()) { - theApp._manager.uninstallApplication(); + theApp._manager.updateProgress(LauncherManager::ProcessType::Uninstall, (float)_splashStep/100); + } + _splashStep++; + } else if (theApp._manager.shouldShutDown()) { + if (LauncherUtils::isProcessWindowOpened(L"interface.exe")) { exit(0); - } else { - theApp._manager.addToLog(_T("Starting login")); - setDrawDialog(DrawStep::DrawLoginLogin); } } - _splashStep++; - } else if (theApp._manager.shouldShutDown()) { - if (LauncherUtils::IsProcessRunning(L"interface.exe")) { - exit(0); + if (theApp._manager.shouldLaunch()) { + if (theApp._manager.needsInstall() || theApp._manager.needsUpdate()) { + auto finishProcess = theApp._manager.needsUpdate() ? DrawStep::DrawProcessFinishUpdate : DrawStep::DrawProcessFinishHq; + setDrawDialog(finishProcess); + } + _applicationWND = theApp._manager.launchApplication(); } } - if (theApp._manager.shouldLaunch()) { - _applicationWND = theApp._manager.launchApplication(); +} + +void CLauncherDlg::setVerticalElement(CWnd* element, int verticalOffset, int heightOffset, bool fromMainWindowBottom) { + CRect elementRec; + CRect windowRec; + if (element != NULL) { + element->GetWindowRect(&elementRec); + ScreenToClient(&elementRec); + int offset = verticalOffset; + if (fromMainWindowBottom) { + GetWindowRect(&windowRec); + ScreenToClient(&windowRec); + int currentDistance = windowRec.bottom - elementRec.bottom; + offset = currentDistance - verticalOffset; + } + elementRec.bottom = elementRec.bottom + offset + heightOffset; + elementRec.top = elementRec.top + offset; + element->MoveWindow(elementRec, FALSE); } } void CLauncherDlg::setDrawDialog(DrawStep step, BOOL isUpdate) { _drawStep = step; + float progress = 0.0f; auto m_pRenderTarget = GetRenderTarget(); auto m_voxelRenderTarget = m_voxel->GetRenderTarget(); + auto m_progressRenderTarget = m_progress->GetRenderTarget(); switch (_drawStep) { case DrawStep::DrawLogo: m_pRenderTarget->BeginDraw(); drawBackground(m_pRenderTarget); + drawLogo(m_pRenderTarget); m_pRenderTarget->EndDraw(); - m_voxelRenderTarget->BeginDraw(); - drawLogo(m_voxelRenderTarget); - m_voxelRenderTarget->EndDraw(); break; case DrawStep::DrawLoginLogin: case DrawStep::DrawLoginErrorOrg: @@ -671,6 +765,7 @@ void CLauncherDlg::setDrawDialog(DrawStep step, BOOL isUpdate) { m_pRenderTarget->EndDraw(); RedrawWindow(); break; + case DrawStep::DrawError: case DrawStep::DrawProcessFinishHq: case DrawStep::DrawProcessFinishUpdate: case DrawStep::DrawProcessUpdate: @@ -686,7 +781,12 @@ void CLauncherDlg::setDrawDialog(DrawStep step, BOOL isUpdate) { drawSmallLogo(m_pRenderTarget); m_pRenderTarget->EndDraw(); RedrawWindow(); - } + } + m_progressRenderTarget->BeginDraw(); + m_progressRenderTarget->Clear(D2D1::ColorF(0.0f, 0.0f, 0.0f, 1.0f)); + drawProgress(m_progressRenderTarget, 1.0f, D2D1::ColorF(0.2f, 0.2f, 0.2f)); + drawProgress(m_progressRenderTarget, theApp._manager.getProgress(), D2D1::ColorF(0.0f, 0.62f, 0.9f)); + m_progressRenderTarget->EndDraw(); m_voxelRenderTarget->BeginDraw(); drawVoxel(m_voxelRenderTarget); m_voxelRenderTarget->EndDraw(); diff --git a/launchers/win32/LauncherDlg.h b/launchers/win32/LauncherDlg.h index 6357c2a5b0..faebc8a822 100644 --- a/launchers/win32/LauncherDlg.h +++ b/launchers/win32/LauncherDlg.h @@ -43,30 +43,33 @@ public: void setDrawDialog(DrawStep step, BOOL isUpdate = FALSE); - // Dialog Data #ifdef AFX_DESIGN_TIME enum { IDD = IDD_LAUNCHER_DIALOG }; #endif - protected: +// Implementation +protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support void startProcess(); void setCustomDialog(); - -// Implementation -protected: - + void setVerticalElement(CWnd* element, int verticalOffset, int heightOffset = 0, bool fromMainWindowBottom = true); BOOL getHQInfo(const CString& orgname); DrawStep _drawStep { DrawStep::DrawLogo }; BOOL getTextFormat(int ResID, TextFormat& formatOut); void showWindows(std::vector windows, bool show); + POINT getMouseCoords(MSG* pMsg); - bool _isConsoleRunning{ false }; - bool _isInstalling{ false }; - bool _isFirstDraw{ false }; - bool _showSplash{ true }; - int _splashStep{ 0 }; + + bool _isConsoleRunning { false }; + bool _isInstalling { false }; + bool _isFirstDraw { false }; + bool _showSplash { true }; + + bool _draggingWindow { false }; + POINT _dragOffset; + + int _splashStep { 0 }; float _logoRotation { 0.0f }; HICON m_hIcon; @@ -81,6 +84,7 @@ protected: CStatic* m_terms; CStatic* m_trouble; CStatic* m_voxel; + CStatic* m_progress; CEdit m_orgname; CEdit m_username; @@ -96,11 +100,11 @@ protected: void drawLogo(CHwndRenderTarget* pRenderTarget); void drawSmallLogo(CHwndRenderTarget* pRenderTarget); void drawVoxel(CHwndRenderTarget* pRenderTarget); + void drawProgress(CHwndRenderTarget* pRenderTarget, float progress, const D2D1::ColorF& color); void prepareLogin(DrawStep step); void prepareProcess(DrawStep step); void prepareChoose(); - void prepareError(); void redrawBanner(const CEdit& edit, CStatic* banner); diff --git a/launchers/win32/LauncherManager.cpp b/launchers/win32/LauncherManager.cpp index 47c84f1124..e56e0e71fc 100644 --- a/launchers/win32/LauncherManager.cpp +++ b/launchers/win32/LauncherManager.cpp @@ -15,31 +15,43 @@ #include "LauncherManager.h" -LauncherManager::LauncherManager() -{ +LauncherManager::LauncherManager() { } - -LauncherManager::~LauncherManager() -{ +LauncherManager::~LauncherManager() { } void LauncherManager::init() { initLog(); addToLog(_T("Getting most recent build")); - getMostRecentBuild(_latestApplicationURL, _latestVersion); - addToLog(_T("Latest version: ") + _latestVersion); - CString currentVersion; - if (isApplicationInstalled(currentVersion, _domainURL, _contentURL, _loggedIn) && _loggedIn) { - addToLog(_T("Installed version: ") + currentVersion); - if (_latestVersion.Compare(currentVersion) == 0) { - addToLog(_T("Already running most recent build. Launching interface.exe")); - _shouldLaunch = TRUE; - _shouldShutdown = TRUE; - } else { - addToLog(_T("New build found. Updating")); + CString response; + LauncherUtils::ResponseError error = getMostRecentBuild(_latestApplicationURL, _latestVersion, response); + if (error == LauncherUtils::ResponseError::NoError) { + addToLog(_T("Latest version: ") + _latestVersion); + CString currentVersion; + if (isApplicationInstalled(currentVersion, _domainURL, _contentURL, _loggedIn) && _loggedIn) { + addToLog(_T("Installed version: ") + currentVersion); + if (_latestVersion.Compare(currentVersion) == 0) { + addToLog(_T("Already running most recent build. Launching interface.exe")); + _shouldLaunch = TRUE; + _shouldShutdown = TRUE; + } else { + addToLog(_T("New build found. Updating")); + _shouldUpdate = TRUE; + } + } else if (_loggedIn) { + addToLog(_T("Interface not found but logged in. Reinstalling")); _shouldUpdate = TRUE; + } else { + _shouldInstall = TRUE; } + } else { + _hasFailed = true; + CString msg; + msg.Format(_T("Getting most recent build has failed with error: %d"), error); + addToLog(msg); + msg.Format(_T("Response: %s"), response); + addToLog(msg); } } @@ -74,8 +86,19 @@ void LauncherManager::closeLog() { } } +void LauncherManager::saveErrorLog() { + CString logPath = _logFile.GetFilePath(); + CString errorLogPath; + auto result = getAndCreatePaths(PathType::Launcher_Directory, errorLogPath); + if (result) { + CString filename; + errorLogPath += _T("log_error.txt"); + closeLog(); + CopyFile(logPath, errorLogPath, FALSE); + } +} + BOOL LauncherManager::installLauncher() { - addToLog(_T("Installing Launcher.")); CString appPath; BOOL result = getAndCreatePaths(PathType::Running_Path, appPath); if (!result) { @@ -93,13 +116,17 @@ BOOL LauncherManager::installLauncher() { if (!_shouldUninstall) { // The installer is not running on the desired location and has to be installed // Kill of running before self-copy - if (LauncherUtils::IsProcessRunning(LAUNCHER_EXE_FILENAME)) { - ShellExecute(NULL, NULL, L"taskkill", L"/F /T /IM " + LAUNCHER_EXE_FILENAME, NULL, SW_HIDE); + addToLog(_T("Installing Launcher.")); + int launcherPID = -1; + if (LauncherUtils::isProcessRunning(LAUNCHER_EXE_FILENAME, launcherPID)) { + if (!LauncherUtils::shutdownProcess(launcherPID, 0)) { + addToLog(_T("Error shutting down the Launcher")); + } } CopyFile(appPath, instalationPath, FALSE); } } else if (_shouldUninstall) { - addToLog(_T("Launching uninstall mode.")); + addToLog(_T("Launching Uninstall mode.")); CString tempPath; if (getAndCreatePaths(PathType::Temp_Directory, tempPath)) { tempPath += _T("\\HQ_uninstaller_tmp.exe"); @@ -111,6 +138,52 @@ BOOL LauncherManager::installLauncher() { return TRUE; } +BOOL LauncherManager::restartLauncher() { + addToLog(_T("Restarting Launcher.")); + CString installDirectory; + if (getAndCreatePaths(PathType::Launcher_Directory, installDirectory)) { + CString installPath = installDirectory + LAUNCHER_EXE_FILENAME; + LauncherUtils::launchApplication(installPath, _T(" --restart")); + exit(0); + } + addToLog(_T("Error restarting Launcher.")); + return FALSE; +} + +void LauncherManager::updateProgress(ProcessType processType, float progress) { + switch (processType) { + case ProcessType::Uninstall: + _progress = progress; + break; + case ProcessType::DownloadContent: + _progress = DOWNLOAD_CONTENT_INSTALL_WEIGHT * progress; + break; + case ProcessType::UnzipContent: + _progress = DOWNLOAD_CONTENT_INSTALL_WEIGHT + + EXTRACT_CONTENT_INSTALL_WEIGHT * progress; + break; + case ProcessType::DownloadApplication: + _progress = !_shouldUpdate ? + (DOWNLOAD_CONTENT_INSTALL_WEIGHT + + EXTRACT_CONTENT_INSTALL_WEIGHT + + DOWNLOAD_APPLICATION_INSTALL_WEIGHT * progress) : + DOWNLOAD_APPLICATION_UPDATE_WEIGHT * progress; + break; + case ProcessType::UnzipApplication: + _progress = !_shouldUpdate ? + (DOWNLOAD_CONTENT_INSTALL_WEIGHT + + EXTRACT_CONTENT_INSTALL_WEIGHT + + DOWNLOAD_APPLICATION_INSTALL_WEIGHT + + EXTRACT_APPLICATION_INSTALL_WEIGHT * progress) : + (DOWNLOAD_APPLICATION_UPDATE_WEIGHT + + EXTRACT_APPLICATION_UPDATE_WEIGHT * progress); + break; + default: + break; + } + TRACE("progress = %f\n", _progress); +} + BOOL LauncherManager::createShortcuts() { CString desktopLnkPath; addToLog(_T("Creating shortcuts.")); @@ -119,7 +192,7 @@ BOOL LauncherManager::createShortcuts() { CString installDir; getAndCreatePaths(PathType::Launcher_Directory, installDir); CString installPath = installDir + LAUNCHER_EXE_FILENAME; - if (!LauncherUtils::CreateLink(installPath, (LPCSTR)CStringA(desktopLnkPath), _T("CLick to Setup and Launch HQ."))) { + if (!LauncherUtils::createLink(installPath, (LPCSTR)CStringA(desktopLnkPath), _T("CLick to Setup and Launch HQ."))) { return FALSE; } CString startLinkPath; @@ -127,13 +200,13 @@ BOOL LauncherManager::createShortcuts() { CString appStartLinkPath = startLinkPath + _T("HQ Launcher.lnk"); CString uniStartLinkPath = startLinkPath + _T("Uninstall HQ.lnk"); CString uniLinkPath = installDir + _T("Uninstall HQ.lnk"); - if (!LauncherUtils::CreateLink(installPath, (LPCSTR)CStringA(appStartLinkPath), _T("CLick to Setup and Launch HQ."))) { + if (!LauncherUtils::createLink(installPath, (LPCSTR)CStringA(appStartLinkPath), _T("CLick to Setup and Launch HQ."))) { return FALSE; } - if (!LauncherUtils::CreateLink(installPath, (LPCSTR)CStringA(uniStartLinkPath), _T("CLick to Uninstall HQ."), _T("--uninstall"))) { + if (!LauncherUtils::createLink(installPath, (LPCSTR)CStringA(uniStartLinkPath), _T("CLick to Uninstall HQ."), _T("--uninstall"))) { return FALSE; } - if (!LauncherUtils::CreateLink(installPath, (LPCSTR)CStringA(uniLinkPath), _T("CLick to Uninstall HQ."), _T("--uninstall"))) { + if (!LauncherUtils::createLink(installPath, (LPCSTR)CStringA(uniLinkPath), _T("CLick to Uninstall HQ."), _T("--uninstall"))) { return FALSE; } return TRUE; @@ -157,9 +230,9 @@ BOOL LauncherManager::isApplicationInstalled(CString& version, CString& domain, CString applicationPath = applicationDir + "interface\\interface.exe"; BOOL isApplicationInstalled = PathFileExistsW(applicationPath); BOOL configFileExist = PathFileExistsW(applicationDir + _T("interface\\config.json")); - if (isApplicationInstalled && configFileExist) { + if (configFileExist) { LauncherUtils::ResponseError status = readConfigJSON(version, domain, content, loggedIn); - return status == LauncherUtils::ResponseError::NoError; + return isApplicationInstalled && status == LauncherUtils::ResponseError::NoError; } return FALSE; } @@ -223,8 +296,9 @@ HWND LauncherManager::launchApplication() { LauncherManager::getAndCreatePaths(PathType::Interface_Directory, installDir); CString interfaceExe = installDir + _T("\\interface.exe"); CString urlParam = _T("--url \"") + _domainURL + ("\" "); - CString scriptsURL = installDir + _T("\\scripts\\simplifiedUI"); - CString scriptsParam = _T("--scripts \"") + scriptsURL + ("\" "); + CString scriptsURL = installDir + _T("\\scripts\\simplifiedUIBootstrapper.js"); + scriptsURL.Replace(_T("\\"), _T("/")); + CString scriptsParam = _T("--defaultScriptsOverride \"") + scriptsURL + ("\" "); CString cacheDir; LauncherManager::getAndCreatePaths(PathType::Content_Directory, cacheDir); CString cacheParam = _T("--cache \"") + cacheDir + ("\" "); @@ -266,7 +340,8 @@ BOOL LauncherManager::createConfigJSON() { return TRUE; } -LauncherUtils::ResponseError LauncherManager::readConfigJSON(CString& version, CString& domain, CString& content, bool& loggedIn) { +LauncherUtils::ResponseError LauncherManager::readConfigJSON(CString& version, CString& domain, + CString& content, bool& loggedIn) { CString configPath; getAndCreatePaths(PathType::Interface_Directory, configPath); configPath += "\\config.json"; @@ -276,7 +351,8 @@ LauncherUtils::ResponseError LauncherManager::readConfigJSON(CString& version, C } Json::Value config; configFile >> config; - if (config["version"].isString() && config["domain"].isString() && + if (config["version"].isString() && + config["domain"].isString() && config["content"].isString()) { loggedIn = config["loggedIn"].asBool(); version = config["version"].asCString(); @@ -293,8 +369,10 @@ LauncherUtils::ResponseError LauncherManager::readOrganizationJSON(const CString CString contentTypeJson = L"content-type:application/json"; CString response; CString url = _T("/organizations/") + hash + _T(".json"); - LauncherUtils::ResponseError error = LauncherUtils::makeHTTPCall(L"HQ Launcher", L"orgs.highfidelity.com", url, - contentTypeJson, CStringA(), response, false); + LauncherUtils::ResponseError error = LauncherUtils::makeHTTPCall(L"HQ Launcher", + L"orgs.highfidelity.com", url, + contentTypeJson, CStringA(), + response, false); if (error != LauncherUtils::ResponseError::NoError) { return error; } @@ -309,11 +387,14 @@ LauncherUtils::ResponseError LauncherManager::readOrganizationJSON(const CString return LauncherUtils::ResponseError::ParsingJSON; } -LauncherUtils::ResponseError LauncherManager::getMostRecentBuild(CString& urlOut, CString& versionOut) { +LauncherUtils::ResponseError LauncherManager::getMostRecentBuild(CString& urlOut, CString& versionOut, + CString& response) { CString contentTypeJson = L"content-type:application/json"; - CString response; - LauncherUtils::ResponseError error = LauncherUtils::makeHTTPCall(L"HQ Launcher", L"thunder.highfidelity.com", L"/builds/api/tags/latest?format=json", - contentTypeJson, CStringA(), response, false); + LauncherUtils::ResponseError error = LauncherUtils::makeHTTPCall(L"HQ Launcher", + L"thunder.highfidelity.com", + L"/builds/api/tags/latest?format=json", + contentTypeJson, CStringA(), + response, false); if (error != LauncherUtils::ResponseError::NoError) { return error; } @@ -341,7 +422,8 @@ LauncherUtils::ResponseError LauncherManager::getMostRecentBuild(CString& urlOut return LauncherUtils::ResponseError::ParsingJSON; } -LauncherUtils::ResponseError LauncherManager::getAccessTokenForCredentials(const CString& username, const CString& password) { +LauncherUtils::ResponseError LauncherManager::getAccessTokenForCredentials(const CString& username, + const CString& password) { CStringA post = "grant_type=password&username="; post += username; post += "&password="; @@ -350,8 +432,11 @@ LauncherUtils::ResponseError LauncherManager::getAccessTokenForCredentials(const CString contentTypeText = L"content-type:application/x-www-form-urlencoded"; CString response; - LauncherUtils::ResponseError error = LauncherUtils::makeHTTPCall(L"HQ Launcher", L"metaverse.highfidelity.com", L"/oauth/token", - contentTypeText, post, response, true); + LauncherUtils::ResponseError error = LauncherUtils::makeHTTPCall(L"HQ Launcher", + L"metaverse.highfidelity.com", + L"/oauth/token", + contentTypeText, post, + response, true); if (error != LauncherUtils::ResponseError::NoError) { return error; } @@ -395,21 +480,19 @@ BOOL LauncherManager::uninstallApplication() { CString installDir; getAndCreatePaths(PathType::Launcher_Directory, installDir); BOOL success = LauncherUtils::deleteFileOrDirectory(installDir); - success = success && (deleteShortcuts()); - success = success && (deleteApplicationRegistryKeys()); + if (success) { + deleteShortcuts(); + deleteApplicationRegistryKeys(); + } return success; } -void LauncherManager::onZipExtracted(ZipType type, int size) { - if (type == ZipType::ZipContent) { +void LauncherManager::onZipExtracted(ProcessType type, int size) { + if (type == ProcessType::UnzipContent) { addToLog(_T("Downloading application.")); downloadApplication(); - } else if (type == ZipType::ZipApplication) { + } else if (type == ProcessType::UnzipApplication) { createShortcuts(); - CString versionPath; - getAndCreatePaths(LauncherManager::PathType::Launcher_Directory, versionPath); - addToLog(_T("Creating config.json")); - createConfigJSON(); addToLog(_T("Launching application.")); _shouldLaunch = TRUE; if (!_shouldUpdate) { @@ -423,10 +506,24 @@ void LauncherManager::onZipExtracted(ZipType type, int size) { BOOL LauncherManager::extractApplication() { CString installPath; getAndCreatePaths(LauncherManager::PathType::Interface_Directory, installPath); - BOOL success = LauncherUtils::unzipFileOnThread(ZipType::ZipApplication, LauncherUtils::cStringToStd(_applicationZipPath), - LauncherUtils::cStringToStd(installPath), [&](int type, int size) { - onZipExtracted((ZipType)type, size); - }); + std::function onExtractFinished = [&](int type, int size) { + addToLog(_T("Creating config.json")); + createConfigJSON(); + if (size > 0) { + onZipExtracted((ProcessType)type, size); + } else { + addToLog(_T("Error decompressing application zip file.")); + _hasFailed = true; + } + }; + std::function onProgress = [&](float progress) { + updateProgress(ProcessType::UnzipApplication, progress); + }; + _currentProcess = ProcessType::UnzipApplication; + BOOL success = LauncherUtils::unzipFileOnThread(ProcessType::UnzipApplication, + LauncherUtils::cStringToStd(_applicationZipPath), + LauncherUtils::cStringToStd(installPath), + onExtractFinished, onProgress); if (success) { addToLog(_T("Created thread for unzipping application.")); } else { @@ -435,13 +532,33 @@ BOOL LauncherManager::extractApplication() { return success; } -void LauncherManager::onFileDownloaded(DownloadType type) { - if (type == DownloadType::DownloadContent) { - addToLog(_T("Installing content.")); - installContent(); - } else if (type == DownloadType::DownloadApplication) { - addToLog(_T("Installing application.")); - extractApplication(); +void LauncherManager::onFileDownloaded(ProcessType type) { + if (type == ProcessType::DownloadContent) { + addToLog(_T("Deleting content directory before install")); + CString contentDir; + getAndCreatePaths(PathType::Content_Directory, contentDir); + LauncherUtils::deleteDirectoryOnThread(contentDir, [&](bool error) { + if (!error) { + addToLog(_T("Installing content.")); + installContent(); + } else { + addToLog(_T("Error deleting content directory.")); + setFailed(true); + } + }); + } else if (type == ProcessType::DownloadApplication) { + addToLog(_T("Deleting application directory before install")); + CString applicationDir; + getAndCreatePaths(PathType::Interface_Directory, applicationDir); + LauncherUtils::deleteDirectoryOnThread(applicationDir, [&](bool error) { + if (!error) { + addToLog(_T("Installing application.")); + extractApplication(); + } else { + addToLog(_T("Error deleting install directory.")); + setFailed(true); + } + }); } } @@ -450,10 +567,22 @@ BOOL LauncherManager::installContent() { std::string contentZipFile = LauncherUtils::cStringToStd(_contentZipPath); CString contentPath; getAndCreatePaths(LauncherManager::PathType::Content_Directory, contentPath); - BOOL success = LauncherUtils::unzipFileOnThread(ZipType::ZipContent, contentZipFile, - LauncherUtils::cStringToStd(contentPath), [&](int type, int size) { - onZipExtracted((ZipType)type, size); - }); + std::function onInstallFinished = [&](int type, int size) { + if (size > 0) { + addToLog(_T("Content zip decompresed.")); + onZipExtracted((ProcessType)type, size); + } + else { + addToLog(_T("Error decompressing content zip file.")); + _hasFailed = true; + } + }; + std::function onProgress = [&](float progress) { + updateProgress(ProcessType::UnzipContent, progress); + }; + _currentProcess = ProcessType::UnzipContent; + BOOL success = LauncherUtils::unzipFileOnThread(ProcessType::UnzipContent, contentZipFile, + LauncherUtils::cStringToStd(contentPath), onInstallFinished, onProgress); if (success) { addToLog(_T("Created thread for unzipping content.")); } else { @@ -463,15 +592,32 @@ BOOL LauncherManager::installContent() { } -BOOL LauncherManager::downloadFile(DownloadType type, const CString& url, CString& outPath) { +BOOL LauncherManager::downloadFile(ProcessType type, const CString& url, CString& outPath) { CString fileName = url.Mid(url.ReverseFind('/') + 1); CString downloadDirectory; BOOL success = getAndCreatePaths(LauncherManager::PathType::Download_Directory, downloadDirectory); outPath = downloadDirectory + fileName; + _currentProcess = type; if (success) { - if (!LauncherUtils::downloadFileOnThread(type, url, outPath, [&](int type) { - onFileDownloaded((DownloadType)type); - })) { + addToLog(_T("Downloading: ") + url); + std::function onDownloadFinished = [&](int type, bool error) { + if (!error) { + onFileDownloaded((ProcessType)type); + } + else { + if (type == ProcessType::DownloadApplication) { + addToLog(_T("Error downloading content.")); + } + else { + addToLog(_T("Error downloading application.")); + } + _hasFailed = true; + } + }; + std::function onProgress = [&](float progress) { + updateProgress(_currentProcess, progress); + }; + if (!LauncherUtils::downloadFileOnThread(type, url, outPath, onDownloadFinished, onProgress)) { success = FALSE; } } @@ -481,10 +627,18 @@ BOOL LauncherManager::downloadFile(DownloadType type, const CString& url, CStrin BOOL LauncherManager::downloadContent() { addToLog(_T("Downloading content.")); CString contentURL = getContentURL(); - return downloadFile(DownloadType::DownloadContent, contentURL, _contentZipPath); + return downloadFile(ProcessType::DownloadContent, contentURL, _contentZipPath); } BOOL LauncherManager::downloadApplication() { CString applicationURL = getLatestInterfaceURL(); - return downloadFile(DownloadType::DownloadApplication, applicationURL, _applicationZipPath); + return downloadFile(ProcessType::DownloadApplication, applicationURL, _applicationZipPath); +} + +void LauncherManager::onCancel() { + if (_currentProcess == ProcessType::UnzipApplication) { + _latestVersion = _T(""); + _version = _T(""); + createConfigJSON(); + } } diff --git a/launchers/win32/LauncherManager.h b/launchers/win32/LauncherManager.h index 6fa7efeeda..cb707e0a14 100644 --- a/launchers/win32/LauncherManager.h +++ b/launchers/win32/LauncherManager.h @@ -19,6 +19,12 @@ const CString DIRECTORY_NAME_CONTENT = _T("content"); const CString EXTRA_PARAMETERS = _T(" --suppress-settings-reset --no-launcher --no-updater"); const CString LAUNCHER_EXE_FILENAME = _T("HQ Launcher.exe"); const bool INSTALL_ZIP = true; +const float DOWNLOAD_CONTENT_INSTALL_WEIGHT = 0.2f; +const float EXTRACT_CONTENT_INSTALL_WEIGHT = 0.1f; +const float DOWNLOAD_APPLICATION_INSTALL_WEIGHT = 0.5f; +const float EXTRACT_APPLICATION_INSTALL_WEIGHT = 0.2f; +const float DOWNLOAD_APPLICATION_UPDATE_WEIGHT = 0.75f; +const float EXTRACT_APPLICATION_UPDATE_WEIGHT = 0.25f; class LauncherManager { @@ -33,16 +39,8 @@ public: StartMenu_Directory, Temp_Directory }; - enum ZipType { - ZipContent = 0, - ZipApplication - }; - enum DownloadType { - DownloadContent = 0, - DownloadApplication - }; enum ErrorType { - ErrorNetworkAuth, + ErrorNetworkAuth = 0, ErrorNetworkUpdate, ErrorNetworkHq, ErrorDownloading, @@ -50,18 +48,26 @@ public: ErrorInstall, ErrorIOFiles }; + enum ProcessType { + DownloadContent, + DownloadApplication, + UnzipContent, + UnzipApplication, + Uninstall + }; LauncherManager(); ~LauncherManager(); void init(); BOOL initLog(); BOOL addToLog(const CString& line); void closeLog(); + void saveErrorLog(); BOOL getAndCreatePaths(PathType type, CString& outPath); BOOL getInstalledVersion(const CString& path, CString& version); BOOL isApplicationInstalled(CString& version, CString& domain, CString& content, bool& loggedIn); LauncherUtils::ResponseError getAccessTokenForCredentials(const CString& username, const CString& password); - LauncherUtils::ResponseError getMostRecentBuild(CString& urlOut, CString& versionOut); + LauncherUtils::ResponseError getMostRecentBuild(CString& urlOut, CString& versionOut, CString& response); LauncherUtils::ResponseError readOrganizationJSON(const CString& hash); LauncherUtils::ResponseError readConfigJSON(CString& version, CString& domain, CString& content, bool& loggedIn); @@ -73,6 +79,7 @@ public: HWND launchApplication(); BOOL uninstallApplication(); BOOL installLauncher(); + BOOL restartLauncher(); // getters const CString& getContentURL() const { return _contentURL; } @@ -82,20 +89,27 @@ public: BOOL shouldLaunch() const { return _shouldLaunch; } BOOL needsUpdate() { return _shouldUpdate; } BOOL needsUninstall() { return _shouldUninstall; } + BOOL needsInstall() { return _shouldInstall; } void setDisplayName(const CString& displayName) { _displayName = displayName; } bool isLoggedIn() { return _loggedIn; } + bool hasFailed() { return _hasFailed; } + void setFailed(bool hasFailed) { _hasFailed = hasFailed; } const CString& getLatestInterfaceURL() const { return _latestApplicationURL; } void uninstall() { _shouldUninstall = true; }; - BOOL downloadFile(DownloadType type, const CString& url, CString& localPath); + BOOL downloadFile(ProcessType type, const CString& url, CString& localPath); BOOL downloadContent(); BOOL downloadApplication(); BOOL installContent(); BOOL extractApplication(); - void onZipExtracted(ZipType type, int size); - void onFileDownloaded(DownloadType type); + void onZipExtracted(ProcessType type, int size); + void onFileDownloaded(ProcessType type); + float getProgress() { return _progress; } + void updateProgress(ProcessType processType, float progress); + void onCancel(); private: + ProcessType _currentProcess { ProcessType::DownloadApplication }; CString _latestApplicationURL; CString _latestVersion; CString _contentURL; @@ -105,11 +119,14 @@ private: CString _tokensJSON; CString _applicationZipPath; CString _contentZipPath; - bool _loggedIn{ false }; - BOOL _shouldUpdate{ FALSE }; - BOOL _shouldUninstall{ FALSE }; - BOOL _shouldShutdown{ FALSE }; - BOOL _shouldLaunch{ FALSE }; + bool _loggedIn { false }; + bool _hasFailed { false }; + BOOL _shouldUpdate { FALSE }; + BOOL _shouldUninstall { FALSE }; + BOOL _shouldInstall { FALSE }; + BOOL _shouldShutdown { FALSE }; + BOOL _shouldLaunch { FALSE }; + float _progress { 0.0f }; CStdioFile _logFile; }; diff --git a/launchers/win32/LauncherUtils.cpp b/launchers/win32/LauncherUtils.cpp index 3ffbd37c58..3ba4b26901 100644 --- a/launchers/win32/LauncherUtils.cpp +++ b/launchers/win32/LauncherUtils.cpp @@ -37,17 +37,53 @@ CString LauncherUtils::urlEncodeString(const CString& url) { return stringOut; } -BOOL LauncherUtils::IsProcessRunning(const wchar_t *processName) { +BOOL LauncherUtils::shutdownProcess(DWORD dwProcessId, UINT uExitCode) { + DWORD dwDesiredAccess = PROCESS_TERMINATE; + BOOL bInheritHandle = FALSE; + HANDLE hProcess = OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId); + if (hProcess == NULL) { + return FALSE; + } + BOOL result = TerminateProcess(hProcess, uExitCode); + CloseHandle(hProcess); + return result; +} + +BOOL CALLBACK LauncherUtils::isWindowOpenedCallback(HWND hWnd, LPARAM lparam) { + ProcessData* processData = reinterpret_cast(lparam); + if (processData) { + DWORD idptr; + GetWindowThreadProcessId(hWnd, &idptr); + if (idptr && (int)(idptr) == processData->processID) { + processData->isOpened = IsWindowVisible(hWnd); + return FALSE; + } + } + return TRUE; +} + +BOOL LauncherUtils::isProcessWindowOpened(const wchar_t *processName) { + ProcessData processData; + BOOL result = isProcessRunning(processName, processData.processID); + if (result) { + EnumWindows(LauncherUtils::isWindowOpenedCallback, reinterpret_cast(&processData)); + return processData.isOpened; + } + return result; +} + +BOOL LauncherUtils::isProcessRunning(const wchar_t *processName, int& processID) { bool exists = false; PROCESSENTRY32 entry; entry.dwSize = sizeof(PROCESSENTRY32); HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); - + if (Process32First(snapshot, &entry)) { while (Process32Next(snapshot, &entry)) { if (!_wcsicmp(entry.szExeFile, processName)) { exists = true; + processID = entry.th32ProcessID; break; } } @@ -56,7 +92,7 @@ BOOL LauncherUtils::IsProcessRunning(const wchar_t *processName) { return exists; } -HRESULT LauncherUtils::CreateLink(LPCWSTR lpszPathObj, LPCSTR lpszPathLink, LPCWSTR lpszDesc, LPCWSTR lpszArgs) { +HRESULT LauncherUtils::createLink(LPCWSTR lpszPathObj, LPCSTR lpszPathLink, LPCWSTR lpszDesc, LPCWSTR lpszArgs) { IShellLink* psl; // Get a pointer to the IShellLink interface. It is assumed that CoInitialize @@ -236,7 +272,9 @@ BOOL LauncherUtils::getFont(const CString& fontName, int fontSize, bool isBold, return TRUE; } -uint64_t LauncherUtils::extractZip(const std::string& zipFile, const std::string& path, std::vector& files) { +uint64_t LauncherUtils::extractZip(const std::string& zipFile, const std::string& path, + std::vector& files, + std::function progressCallback) { { CString msg; msg.Format(_T("Reading zip file %s, extracting to %s"), CString(zipFile.c_str()), CString(path.c_str())); @@ -256,40 +294,58 @@ uint64_t LauncherUtils::extractZip(const std::string& zipFile, const std::string theApp._manager.addToLog(msg); return 0; } - int fileCount = (int)mz_zip_reader_get_num_files(&zip_archive); - if (fileCount == 0) { - theApp._manager.addToLog(_T("Zip archive has a file count of 0")); + { + CString msg; + msg.Format(_T("Zip archive has a file count of %d"), fileCount); + theApp._manager.addToLog(msg); + } + if (fileCount == 0) { mz_zip_reader_end(&zip_archive); return 0; } mz_zip_archive_file_stat file_stat; if (!mz_zip_reader_file_stat(&zip_archive, 0, &file_stat)) { theApp._manager.addToLog(_T("Zip archive cannot be stat'd")); - mz_zip_reader_end(&zip_archive); return 0; } // Get root folder CString lastDir = _T(""); uint64_t totalSize = 0; + uint64_t totalCompressedSize = 0; + bool _shouldFail = false; for (int i = 0; i < fileCount; i++) { if (!mz_zip_reader_file_stat(&zip_archive, i, &file_stat)) continue; std::string filename = file_stat.m_filename; std::replace(filename.begin(), filename.end(), '/', '\\'); CString fullFilename = CString(path.c_str()) + "\\" + CString(filename.c_str()); if (mz_zip_reader_is_file_a_directory(&zip_archive, i)) { - if (SHCreateDirectoryEx(NULL, fullFilename, NULL) || ERROR_ALREADY_EXISTS == GetLastError()) { - break; - } else { - continue; + int error = SHCreateDirectoryEx(NULL, fullFilename, NULL); + if (error == ERROR_BAD_PATHNAME || + error == ERROR_FILENAME_EXCED_RANGE || + error == ERROR_PATH_NOT_FOUND || + error == ERROR_CANCELLED) { + CString msg; + msg.Format(_T("Unzipping error: %d creating folder: %s"), error, fullFilename); + theApp._manager.addToLog(msg); + mz_zip_reader_end(&zip_archive); + return 0; } + continue; } CT2A destFile(fullFilename); if (mz_zip_reader_extract_to_file(&zip_archive, i, destFile, 0)) { + totalCompressedSize += (uint64_t)file_stat.m_comp_size; totalSize += (uint64_t)file_stat.m_uncomp_size; + progressCallback((float)totalCompressedSize / (float)zip_archive.m_archive_size); files.emplace_back(destFile); + } else { + CString msg; + msg.Format(_T("Error unzipping the file: %s"), fullFilename); + theApp._manager.addToLog(msg); + _shouldFail = true; } } @@ -414,41 +470,40 @@ BOOL LauncherUtils::hMac256(const CString& cmessage, const char* keystr, CString DWORD WINAPI LauncherUtils::unzipThread(LPVOID lpParameter) { UnzipThreadData& data = *((UnzipThreadData*)lpParameter); - uint64_t size = LauncherUtils::extractZip(data._zipFile, data._path, std::vector()); + uint64_t size = LauncherUtils::extractZip(data._zipFile, data._path, std::vector(), data.progressCallback); int mb_size = (int)(size * 0.001f); data.callback(data._type, mb_size); delete &data; return 0; } -DWORD WINAPI LauncherUtils::downloadThread(LPVOID lpParameter) -{ +DWORD WINAPI LauncherUtils::downloadThread(LPVOID lpParameter) { DownloadThreadData& data = *((DownloadThreadData*)lpParameter); - auto hr = URLDownloadToFile(0, data._url, data._file, 0, NULL); - data.callback(data._type); + ProgressCallback progressCallback; + progressCallback.setProgressCallback(data.progressCallback); + auto hr = URLDownloadToFile(0, data._url, data._file, 0, + static_cast(&progressCallback)); + data.callback(data._type, hr != S_OK); return 0; } -DWORD WINAPI LauncherUtils::deleteDirectoriesThread(LPVOID lpParameter) { +DWORD WINAPI LauncherUtils::deleteDirectoryThread(LPVOID lpParameter) { DeleteThreadData& data = *((DeleteThreadData*)lpParameter); - DeleteDirError error = DeleteDirError::NoErrorDeleting; - if (!LauncherUtils::deleteFileOrDirectory(data._applicationDir)) { - error = DeleteDirError::ErrorDeletingApplicationDir; - } - if (!LauncherUtils::deleteFileOrDirectory(data._downloadsDir)) { - error = error == NoError ? DeleteDirError::ErrorDeletingDownloadsDir : DeleteDirError::ErrorDeletingBothDirs; - } - data.callback(error); + BOOL success = LauncherUtils::deleteFileOrDirectory(data._dirPath); + data.callback(!success); return 0; } -BOOL LauncherUtils::unzipFileOnThread(int type, const std::string& zipFile, const std::string& path, std::function callback) { +BOOL LauncherUtils::unzipFileOnThread(int type, const std::string& zipFile, const std::string& path, + std::function callback, + std::function progressCallback) { DWORD myThreadID; UnzipThreadData* unzipThreadData = new UnzipThreadData(); unzipThreadData->_type = type; unzipThreadData->_zipFile = zipFile; unzipThreadData->_path = path; unzipThreadData->setCallback(callback); + unzipThreadData->setProgressCallback(progressCallback); HANDLE myHandle = CreateThread(0, 0, unzipThread, unzipThreadData, 0, &myThreadID); if (myHandle) { CloseHandle(myHandle); @@ -457,13 +512,16 @@ BOOL LauncherUtils::unzipFileOnThread(int type, const std::string& zipFile, cons return FALSE; } -BOOL LauncherUtils::downloadFileOnThread(int type, const CString& url, const CString& file, std::function callback) { +BOOL LauncherUtils::downloadFileOnThread(int type, const CString& url, const CString& file, + std::function callback, + std::function progressCallback) { DWORD myThreadID; DownloadThreadData* downloadThreadData = new DownloadThreadData(); downloadThreadData->_type = type; downloadThreadData->_url = url; downloadThreadData->_file = file; downloadThreadData->setCallback(callback); + downloadThreadData->setProgressCallback(progressCallback); HANDLE myHandle = CreateThread(0, 0, downloadThread, downloadThreadData, 0, &myThreadID); if (myHandle) { CloseHandle(myHandle); @@ -472,15 +530,12 @@ BOOL LauncherUtils::downloadFileOnThread(int type, const CString& url, const CSt return FALSE; } -BOOL LauncherUtils::deleteDirectoriesOnThread(const CString& applicationDir, - const CString& downloadsDir, - std::function callback) { +BOOL LauncherUtils::deleteDirectoryOnThread(const CString& dirPath, std::function callback) { DWORD myThreadID; DeleteThreadData* deleteThreadData = new DeleteThreadData(); - deleteThreadData->_applicationDir = applicationDir; - deleteThreadData->_downloadsDir = downloadsDir; + deleteThreadData->_dirPath = dirPath; deleteThreadData->setCallback(callback); - HANDLE myHandle = CreateThread(0, 0, deleteDirectoriesThread, deleteThreadData, 0, &myThreadID); + HANDLE myHandle = CreateThread(0, 0, deleteDirectoryThread, deleteThreadData, 0, &myThreadID); if (myHandle) { CloseHandle(myHandle); return TRUE; diff --git a/launchers/win32/LauncherUtils.h b/launchers/win32/LauncherUtils.h index a1cc553128..3e07d2af05 100644 --- a/launchers/win32/LauncherUtils.h +++ b/launchers/win32/LauncherUtils.h @@ -15,9 +15,57 @@ #include "libs/json/json.h" #include "libs/miniz.h" -class LauncherUtils -{ +class LauncherUtils { public: + class ProgressCallback : public IBindStatusCallback { + public: + HRESULT __stdcall QueryInterface(const IID &, void **) { + return E_NOINTERFACE; + } + ULONG STDMETHODCALLTYPE AddRef(void) { + return 1; + } + ULONG STDMETHODCALLTYPE Release(void) { + return 1; + } + HRESULT STDMETHODCALLTYPE OnStartBinding(DWORD dwReserved, IBinding *pib) { + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE GetPriority(LONG *pnPriority) { + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE OnLowResource(DWORD reserved) { + return S_OK; + } + virtual HRESULT STDMETHODCALLTYPE OnStopBinding(HRESULT hresult, LPCWSTR szError) { + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE GetBindInfo(DWORD *grfBINDF, BINDINFO *pbindinfo) { + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE OnDataAvailable(DWORD grfBSCF, DWORD dwSize, + FORMATETC *pformatetc, STGMEDIUM *pstgmed) { + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE OnObjectAvailable(REFIID riid, IUnknown *punk) { + return E_NOTIMPL; + } + + virtual HRESULT __stdcall OnProgress(ULONG ulProgress, ULONG ulProgressMax, + ULONG ulStatusCode, LPCWSTR szStatusText) { + float progress = (float)ulProgress / ulProgressMax; + if (!isnan(progress)) { + onProgressCallback(progress); + } + return S_OK; + } + void setProgressCallback(std::function fn) { + onProgressCallback = std::bind(fn, std::placeholders::_1); + } + private: + std::function onProgressCallback; + }; + enum ResponseError { Open = 0, Connect, @@ -30,21 +78,18 @@ public: NoError }; - enum DeleteDirError { - NoErrorDeleting = 0, - ErrorDeletingApplicationDir, - ErrorDeletingDownloadsDir, - ErrorDeletingBothDirs - }; - struct DownloadThreadData { int _type; CString _url; CString _file; - std::function callback; - // function(type) - void setCallback(std::function fn) { - callback = std::bind(fn, std::placeholders::_1); + std::function callback; + std::function progressCallback; + // function(type, errorType) + void setCallback(std::function fn) { + callback = std::bind(fn, std::placeholders::_1, std::placeholders::_2); + } + void setProgressCallback(std::function fn) { + progressCallback = std::bind(fn, std::placeholders::_1); } }; @@ -54,16 +99,28 @@ public: std::string _path; // function(type, size) std::function callback; + std::function progressCallback; void setCallback(std::function fn) { callback = std::bind(fn, std::placeholders::_1, std::placeholders::_2); } + void setProgressCallback(std::function fn) { + progressCallback = std::bind(fn, std::placeholders::_1); + } }; struct DeleteThreadData { - CString _applicationDir; - CString _downloadsDir; - std::function callback; - void setCallback(std::function fn) { callback = std::bind(fn, std::placeholders::_1); } + CString _dirPath; + std::function callback; + std::function progressCallback; + void setCallback(std::function fn) { callback = std::bind(fn, std::placeholders::_1); } + void setProgressCallback(std::function fn) { + progressCallback = std::bind(fn, std::placeholders::_1); + } + }; + + struct ProcessData { + int processID = -1; + BOOL isOpened = FALSE; }; static BOOL parseJSON(const CString& jsonTxt, Json::Value& jsonObject); @@ -73,19 +130,27 @@ public: static std::string cStringToStd(CString cstring); static BOOL getFont(const CString& fontName, int fontSize, bool isBold, CFont& fontOut); static BOOL launchApplication(LPCWSTR lpApplicationName, LPTSTR cmdArgs = _T("")); - static BOOL IsProcessRunning(const wchar_t *processName); + static BOOL CALLBACK isWindowOpenedCallback(HWND hWnd, LPARAM lparam); + static BOOL isProcessRunning(const wchar_t *processName, int& processID); + static BOOL isProcessWindowOpened(const wchar_t *processName); + static BOOL shutdownProcess(DWORD dwProcessId, UINT uExitCode); static BOOL insertRegistryKey(const std::string& regPath, const std::string& name, const std::string& value); static BOOL insertRegistryKey(const std::string& regPath, const std::string& name, DWORD value); static BOOL deleteFileOrDirectory(const CString& dirPath, bool noRecycleBin = true); - static HRESULT CreateLink(LPCWSTR lpszPathObj, LPCSTR lpszPathLink, LPCWSTR lpszDesc, LPCWSTR lpszArgs = _T("")); + static HRESULT createLink(LPCWSTR lpszPathObj, LPCSTR lpszPathLink, LPCWSTR lpszDesc, LPCWSTR lpszArgs = _T("")); static BOOL hMac256(const CString& message, const char* key, CString& hashOut); - static uint64_t extractZip(const std::string& zipFile, const std::string& path, std::vector& files); + static uint64_t extractZip(const std::string& zipFile, const std::string& path, + std::vector& files, + std::function progressCallback); static BOOL deleteRegistryKey(const CString& registryPath); - static BOOL unzipFileOnThread(int type, const std::string& zipFile, const std::string& path, std::function callback); - static BOOL downloadFileOnThread(int type, const CString& url, const CString& file, std::function callback); - static BOOL deleteDirectoriesOnThread(const CString& applicationDir, - const CString& downloadsDir, - std::function callback); + static BOOL unzipFileOnThread(int type, const std::string& zipFile, const std::string& path, + std::function callback, + std::function progressCallback); + static BOOL downloadFileOnThread(int type, const CString& url, const CString& file, + std::function callback, + std::function progressCallback); + static BOOL deleteDirectoryOnThread(const CString& dirPath, std::function callback); + static CString urlEncodeString(const CString& url); static HWND executeOnForeground(const CString& path, const CString& params); @@ -93,5 +158,5 @@ private: // Threads static DWORD WINAPI unzipThread(LPVOID lpParameter); static DWORD WINAPI downloadThread(LPVOID lpParameter); - static DWORD WINAPI deleteDirectoriesThread(LPVOID lpParameter); + static DWORD WINAPI deleteDirectoryThread(LPVOID lpParameter); }; \ No newline at end of file diff --git a/launchers/win32/resource.h b/launchers/win32/resource.h index f5a1e3ef07..74c62b75cb 100644 --- a/launchers/win32/resource.h +++ b/launchers/win32/resource.h @@ -26,6 +26,7 @@ #define IDC_TERMS_LINK 1022 #define IDC_TROUBLE 1023 #define IDC_VOXEL 1024 +#define IDC_PROGRESS 1025 #define IDC_TROUBLE_LINK 1027 // Next default values for new objects diff --git a/libraries/animation/src/AnimVariant.cpp b/libraries/animation/src/AnimVariant.cpp index cf7228b27b..930dbed2d9 100644 --- a/libraries/animation/src/AnimVariant.cpp +++ b/libraries/animation/src/AnimVariant.cpp @@ -159,15 +159,15 @@ std::map AnimVariantMap::toDebugMap() const { arg(QString::number(value.y, 'f', 3)). arg(QString::number(value.z, 'f', 3)). arg(QString::number(value.w, 'f', 3)); - break; */ + break; } case AnimVariant::Type::String: // To prevent filling up anim stats, don't show string values /* result[pair.first] = pair.second.getString(); - break; */ + break; default: // invalid AnimVariant::Type assert(false); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index fb7eddd582..5af98100dc 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1108,7 +1108,7 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const batch.setModelTransform(textTransform); { PROFILE_RANGE_BATCH(batch, __FUNCTION__":renderText"); - renderer->draw(batch, text_x, -text_y, nameUTF8.data(), textColor, glm::vec2(-1.0f), forward); + renderer->draw(batch, text_x, -text_y, nameUTF8.data(), textColor, glm::vec2(-1.0f), true, forward); } } } diff --git a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp index d8f24208b0..40b65c54a1 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp @@ -331,18 +331,19 @@ void SkeletonModel::renderBoundingCollisionShapes(RenderArgs* args, gpu::Batch& // draw a blue sphere at the capsule top point glm::vec3 topPoint = _translation + _rotation * (scale * (_boundingCapsuleLocalOffset + (0.5f * _boundingCapsuleHeight) * Vectors::UNIT_Y)); batch.setModelTransform(Transform().setTranslation(topPoint).postScale(scale * _boundingCapsuleRadius)); - geometryCache->renderSolidSphereInstance(args, batch, glm::vec4(0.6f, 0.6f, 0.8f, alpha)); + auto pipeline = geometryCache->getShapePipelinePointer(alpha < 1.0f, false, args->_renderMethod == render::Args::RenderMethod::FORWARD); + geometryCache->renderSolidSphereInstance(args, batch, glm::vec4(0.6f, 0.6f, 0.8f, alpha), pipeline); // draw a yellow sphere at the capsule bottom point glm::vec3 bottomPoint = topPoint - _rotation * glm::vec3(0.0f, scale * _boundingCapsuleHeight, 0.0f); batch.setModelTransform(Transform().setTranslation(bottomPoint).postScale(scale * _boundingCapsuleRadius)); - geometryCache->renderSolidSphereInstance(args, batch, glm::vec4(0.8f, 0.8f, 0.6f, alpha)); + geometryCache->renderSolidSphereInstance(args, batch, glm::vec4(0.8f, 0.8f, 0.6f, alpha), pipeline); // draw a green cylinder between the two points float capsuleDiameter = 2.0f * _boundingCapsuleRadius; glm::vec3 cylinderDimensions = glm::vec3(capsuleDiameter, _boundingCapsuleHeight, capsuleDiameter); batch.setModelTransform(Transform().setScale(scale * cylinderDimensions).setRotation(_rotation).setTranslation(0.5f * (topPoint + bottomPoint))); - geometryCache->renderSolidShapeInstance(args, batch, GeometryCache::Shape::Cylinder, glm::vec4(0.6f, 0.8f, 0.6f, alpha)); + geometryCache->renderSolidShapeInstance(args, batch, GeometryCache::Shape::Cylinder, glm::vec4(0.6f, 0.8f, 0.6f, alpha), pipeline); } bool SkeletonModel::hasSkeleton() { diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index cb14d7ef41..0c7054424f 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -280,6 +280,10 @@ AvatarSharedPointer AvatarHashMap::parseAvatarData(QSharedPointer()->getMaterial(_materialData); } if (_materialResource) { @@ -280,4 +280,4 @@ void MaterialBaker::setMaterials(const QHash& materials, void MaterialBaker::setMaterials(const NetworkMaterialResourcePointer& materialResource) { _materialResource = materialResource; -} \ No newline at end of file +} diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index b8912d95b6..a35496f88e 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -113,14 +113,8 @@ gpu::PipelinePointer Basic2DWindowOpenGLDisplayPlugin::getRenderTexturePipeline( #if defined(Q_OS_ANDROID) return _linearToSRGBPipeline; #else - -#ifndef USE_GLES - return _SRGBToLinearPipeline; -#else return _drawTexturePipeline; #endif - -#endif } void Basic2DWindowOpenGLDisplayPlugin::compositeExtra() { diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 75cdf5ebef..ebbf888e83 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -392,13 +392,11 @@ void OpenGLDisplayPlugin::customizeContext() { _drawTexturePipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTexture), scissorState); - _linearToSRGBPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTextureGammaLinearToSRGB), scissorState); + _linearToSRGBPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTextureLinearToSRGB), scissorState); - _SRGBToLinearPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTextureGammaSRGBToLinear), scissorState); + _SRGBToLinearPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTextureSRGBToLinear), scissorState); - _hudPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTexture), blendState); - - _mirrorHUDPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTextureMirroredX), blendState); + _hudPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTextureSRGBToLinear), blendState); _cursorPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTransformedTexture), blendState); } @@ -413,7 +411,6 @@ void OpenGLDisplayPlugin::uncustomizeContext() { _SRGBToLinearPipeline.reset(); _cursorPipeline.reset(); _hudPipeline.reset(); - _mirrorHUDPipeline.reset(); _compositeFramebuffer.reset(); withPresentThreadLock([&] { @@ -582,20 +579,18 @@ void OpenGLDisplayPlugin::updateFrameData() { }); } -std::function OpenGLDisplayPlugin::getHUDOperator() { +std::function OpenGLDisplayPlugin::getHUDOperator() { auto hudPipeline = _hudPipeline; - auto hudMirrorPipeline = _mirrorHUDPipeline; auto hudStereo = isStereo(); auto hudCompositeFramebufferSize = _compositeFramebuffer->getSize(); std::array hudEyeViewports; for_each_eye([&](Eye eye) { hudEyeViewports[eye] = eyeViewport(eye); }); - return [=](gpu::Batch& batch, const gpu::TexturePointer& hudTexture, bool mirror) { - auto pipeline = mirror ? hudMirrorPipeline : hudPipeline; - if (pipeline && hudTexture) { + return [=](gpu::Batch& batch, const gpu::TexturePointer& hudTexture) { + if (hudPipeline && hudTexture) { batch.enableStereo(false); - batch.setPipeline(pipeline); + batch.setPipeline(hudPipeline); batch.setResourceTexture(0, hudTexture); if (hudStereo) { for_each_eye([&](Eye eye) { @@ -642,7 +637,7 @@ void OpenGLDisplayPlugin::compositeScene() { batch.setStateScissorRect(ivec4(uvec2(), _compositeFramebuffer->getSize())); batch.resetViewTransform(); batch.setProjectionTransform(mat4()); - batch.setPipeline(getCompositeScenePipeline()); + batch.setPipeline(_drawTexturePipeline); batch.setResourceTexture(0, _currentFrame->framebuffer->getRenderBuffer(0)); batch.draw(gpu::TRIANGLE_STRIP, 4); }); @@ -905,7 +900,7 @@ OpenGLDisplayPlugin::~OpenGLDisplayPlugin() { void OpenGLDisplayPlugin::updateCompositeFramebuffer() { auto renderSize = glm::uvec2(getRecommendedRenderSize()); if (!_compositeFramebuffer || _compositeFramebuffer->getSize() != renderSize) { - _compositeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("OpenGLDisplayPlugin::composite", gpu::Element::COLOR_RGBA_32, renderSize.x, renderSize.y)); + _compositeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("OpenGLDisplayPlugin::composite", gpu::Element::COLOR_SRGBA_32, renderSize.x, renderSize.y)); } } @@ -964,7 +959,3 @@ gpu::PipelinePointer OpenGLDisplayPlugin::getRenderTexturePipeline() { return _drawTexturePipeline; } -gpu::PipelinePointer OpenGLDisplayPlugin::getCompositeScenePipeline() { - return _drawTexturePipeline; -} - diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index 777c74822a..6fb36bff90 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -80,7 +80,7 @@ public: // Three threads, one for rendering, one for texture transfers, one reserved for the GL driver int getRequiredThreadCount() const override { return 3; } - virtual std::function getHUDOperator() override; + virtual std::function getHUDOperator() override; void copyTextureToQuickFramebuffer(NetworkTexturePointer source, QOpenGLFramebufferObject* target, GLsync* fenceSync) override; @@ -162,7 +162,6 @@ protected: float _compositeHUDAlpha{ 1.0f }; virtual gpu::PipelinePointer getRenderTexturePipeline(); - virtual gpu::PipelinePointer getCompositeScenePipeline(); struct CursorData { QImage image; diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp index 3952c2c90e..3cec5e8265 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp @@ -413,7 +413,7 @@ void HmdDisplayPlugin::HUDRenderer::build() { pipeline = gpu::Pipeline::create(program, state); } -std::function HmdDisplayPlugin::HUDRenderer::render() { +std::function HmdDisplayPlugin::HUDRenderer::render() { auto hudPipeline = pipeline; auto hudFormat = format; auto hudVertices = vertices; @@ -421,7 +421,7 @@ std::function HmdDis auto hudUniformBuffer = uniformsBuffer; auto hudUniforms = uniforms; auto hudIndexCount = indexCount; - return [=](gpu::Batch& batch, const gpu::TexturePointer& hudTexture, bool mirror) { + return [=](gpu::Batch& batch, const gpu::TexturePointer& hudTexture) { if (hudPipeline && hudTexture) { batch.setPipeline(hudPipeline); @@ -436,9 +436,6 @@ std::function HmdDis auto compositorHelper = DependencyManager::get(); glm::mat4 modelTransform = compositorHelper->getUiTransform(); - if (mirror) { - modelTransform = glm::scale(modelTransform, glm::vec3(-1, 1, 1)); - } batch.setModelTransform(modelTransform); batch.setResourceTexture(0, hudTexture); @@ -471,7 +468,7 @@ void HmdDisplayPlugin::compositePointer() { }); } -std::function HmdDisplayPlugin::getHUDOperator() { +std::function HmdDisplayPlugin::getHUDOperator() { return _hudRenderer.render(); } diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h index 9942222f48..a381f04689 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h @@ -48,7 +48,7 @@ public: void pluginUpdate() override {}; - std::function getHUDOperator() override; + std::function getHUDOperator() override; virtual StencilMaskMode getStencilMaskMode() const override { return StencilMaskMode::PAINT; } signals: @@ -123,6 +123,6 @@ private: static const int VERTEX_STRIDE { sizeof(Vertex) }; void build(); - std::function render(); + std::function render(); } _hudRenderer; }; diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index bea04f106b..b9fda690dd 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -69,6 +69,7 @@ public: virtual PacketType getExpectedPacketType() const override { return PacketType::EntityData; } // Returns the priority at which an entity should be loaded. Higher values indicate higher priority. + static CalculateEntityLoadingPriority getEntityLoadingPriorityOperator() { return _calculateEntityLoadingPriorityFunc; } static float getEntityLoadingPriority(const EntityItem& item) { return _calculateEntityLoadingPriorityFunc(item); } static void setEntityLoadingPriorityFunction(CalculateEntityLoadingPriority fn) { _calculateEntityLoadingPriorityFunc = fn; } diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index 01d31856e0..11e369b532 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -173,19 +173,22 @@ render::hifi::Layer EntityRenderer::getHifiRenderLayer() const { } ItemKey EntityRenderer::getKey() { + ItemKey::Builder builder = ItemKey::Builder().withTypeShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); + if (isTransparent()) { - return ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); + builder.withTransparent(); + } else if (_canCastShadow) { + builder.withShadowCaster(); } - // This allows shapes to cast shadows - if (_canCastShadow) { - return ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(getTagMask()).withShadowCaster().withLayer(getHifiRenderLayer()); - } else { - return ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); + if (!_visible) { + builder.withInvisible(); } + + return builder; } -uint32_t EntityRenderer::metaFetchMetaSubItems(ItemIDs& subItems) { +uint32_t EntityRenderer::metaFetchMetaSubItems(ItemIDs& subItems) const { if (Item::isValidID(_renderItemID)) { subItems.emplace_back(_renderItemID); return 1; diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index 39f9ad091e..1db4cfdf53 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -62,7 +62,7 @@ public: static glm::vec4 calculatePulseColor(const glm::vec4& color, const PulsePropertyGroup& pulseProperties, quint64 start); - virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) override; + virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) const override; virtual Item::Bound getBound() override; protected: diff --git a/libraries/entities-renderer/src/RenderableGridEntityItem.cpp b/libraries/entities-renderer/src/RenderableGridEntityItem.cpp index 31969e36fc..d8f0d93bb6 100644 --- a/libraries/entities-renderer/src/RenderableGridEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableGridEntityItem.cpp @@ -122,7 +122,7 @@ void GridEntityRenderer::doRender(RenderArgs* args) { forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD; }); - if (!_visible) { + if (!_visible || color.a == 0.0f) { return; } diff --git a/libraries/entities-renderer/src/RenderableImageEntityItem.cpp b/libraries/entities-renderer/src/RenderableImageEntityItem.cpp index 20d10c6fd4..3a4dbf5c6f 100644 --- a/libraries/entities-renderer/src/RenderableImageEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableImageEntityItem.cpp @@ -111,9 +111,9 @@ void ImageEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce void* key = (void*)this; AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity]() { withWriteLock([&] { - _dimensions = entity->getScaledDimensions(); updateModelTransformAndBound(); _renderTransform = getModelTransform(); + _renderTransform.postScale(entity->getScaledDimensions()); }); }); } @@ -152,14 +152,12 @@ void ImageEntityRenderer::doRender(RenderArgs* args) { NetworkTexturePointer texture; QRect subImage; glm::vec4 color; - glm::vec3 dimensions; Transform transform; withReadLock([&] { texture = _texture; subImage = _subImage; color = glm::vec4(toGlm(_color), _alpha); color = EntityRenderer::calculatePulseColor(color, _pulseProperties, _created); - dimensions = _dimensions; transform = _renderTransform; }); @@ -171,7 +169,6 @@ void ImageEntityRenderer::doRender(RenderArgs* args) { gpu::Batch* batch = args->_batch; transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); - transform.postScale(dimensions); batch->setModelTransform(transform); batch->setResourceTexture(0, texture->getGPUTexture()); @@ -200,16 +197,13 @@ void ImageEntityRenderer::doRender(RenderArgs* args) { float maxSize = glm::max(fromImage.width(), fromImage.height()); float x = _keepAspectRatio ? fromImage.width() / (2.0f * maxSize) : 0.5f; - float y = _keepAspectRatio ? -fromImage.height() / (2.0f * maxSize) : -0.5f; + float y = _keepAspectRatio ? fromImage.height() / (2.0f * maxSize) : 0.5f; - glm::vec2 topLeft(-x, -y); - glm::vec2 bottomRight(x, y); - glm::vec2 texCoordTopLeft((fromImage.x() + 0.5f) / imageWidth, (fromImage.y() + 0.5f) / imageHeight); - glm::vec2 texCoordBottomRight((fromImage.x() + fromImage.width() - 0.5f) / imageWidth, - (fromImage.y() + fromImage.height() - 0.5f) / imageHeight); + glm::vec2 texCoordBottomLeft((fromImage.x() + 0.5f) / imageWidth, (fromImage.y() + fromImage.height() - 0.5f) / imageHeight); + glm::vec2 texCoordTopRight((fromImage.x() + fromImage.width() - 0.5f) / imageWidth, (fromImage.y() + 0.5f) / imageHeight); DependencyManager::get()->renderQuad( - *batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, + *batch, glm::vec2(-x, -y), glm::vec2(x, y), texCoordBottomLeft, texCoordTopRight, color, _geometryId ); diff --git a/libraries/entities-renderer/src/RenderableImageEntityItem.h b/libraries/entities-renderer/src/RenderableImageEntityItem.h index d60b38fe65..e686452fa5 100644 --- a/libraries/entities-renderer/src/RenderableImageEntityItem.h +++ b/libraries/entities-renderer/src/RenderableImageEntityItem.h @@ -47,8 +47,6 @@ private: PulsePropertyGroup _pulseProperties; BillboardMode _billboardMode; - glm::vec3 _dimensions; - int _geometryId { 0 }; }; diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp index 348c703e3d..cf549ea4ac 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp @@ -174,7 +174,7 @@ void MaterialEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPo } if (urlChanged && !usingMaterialData) { - _networkMaterial = MaterialCache::instance().getMaterial(_materialURL); + _networkMaterial = DependencyManager::get()->getMaterial(_materialURL); auto onMaterialRequestFinished = [this, oldParentID, oldParentMaterialName, newCurrentMaterialName](bool success) { if (success) { deleteMaterial(oldParentID, oldParentMaterialName); @@ -432,4 +432,4 @@ void MaterialEntityRenderer::applyMaterial() { // if we've reached this point, we couldn't find our parent, so we need to try again later _retryApply = true; -} \ No newline at end of file +} diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index a109254f7f..e4b491ae77 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1073,7 +1073,7 @@ ItemKey ModelEntityRenderer::getKey() { return _itemKey; } -uint32_t ModelEntityRenderer::metaFetchMetaSubItems(ItemIDs& subItems) { +uint32_t ModelEntityRenderer::metaFetchMetaSubItems(ItemIDs& subItems) const { if (_model) { auto metaSubItems = _model->fetchRenderItemIDs(); subItems.insert(subItems.end(), metaSubItems.begin(), metaSubItems.end()); @@ -1519,7 +1519,8 @@ void ModelEntityRenderer::doRender(RenderArgs* args) { static glm::vec4 greenColor(0.0f, 1.0f, 0.0f, 1.0f); gpu::Batch& batch = *args->_batch; batch.setModelTransform(getModelTransform()); // we want to include the scale as well - DependencyManager::get()->renderWireCubeInstance(args, batch, greenColor); + auto geometryCache = DependencyManager::get(); + geometryCache->renderWireCubeInstance(args, batch, greenColor, geometryCache->getShapePipelinePointer(false, false, args->_renderMethod == Args::RenderMethod::FORWARD)); #if WANT_EXTRA_DEBUGGING ModelPointer model; diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index ee6e7d0b04..7f84b3ae62 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -154,7 +154,7 @@ protected: void setKey(bool didVisualGeometryRequestSucceed); virtual ItemKey getKey() override; - virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) override; + virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) const override; virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override; virtual bool needsRenderUpdate() const override; diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index d517ecd026..36f8ccf8f6 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -23,7 +23,7 @@ static uint8_t CUSTOM_PIPELINE_NUMBER = 0; static gpu::Stream::FormatPointer _vertexFormat; static std::weak_ptr _texturedPipeline; -static ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key, gpu::Batch& batch) { +static ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key, RenderArgs* args) { auto texturedPipeline = _texturedPipeline.lock(); if (!texturedPipeline) { auto state = std::make_shared(); diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index adf0a2d162..3adeecabcc 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -34,9 +34,7 @@ #include "EntityTreeRenderer.h" -#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT -# include -#endif +#include #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic push @@ -1553,52 +1551,49 @@ using namespace render; using namespace render::entities; static uint8_t CUSTOM_PIPELINE_NUMBER; -static gpu::PipelinePointer _pipelines[2]; -static gpu::PipelinePointer _wireframePipelines[2]; +static std::map, ShapePipelinePointer> _pipelines; static gpu::Stream::FormatPointer _vertexFormat; -ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key, gpu::Batch& batch) { - if (!_pipelines[0]) { +ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key, RenderArgs* args) { + // FIXME: custom pipelines like this don't handle shadows or renderLayers correctly + + if (_pipelines.empty()) { using namespace shader::entities_renderer::program; - int programsIds[2] = { polyvox, polyvox_fade }; - auto state = std::make_shared(); - state->setCullMode(gpu::State::CULL_BACK); - state->setDepthTest(true, true, gpu::LESS_EQUAL); - PrepareStencil::testMaskDrawShape(*state); + static const std::vector> keys = { + std::make_tuple(false, false, polyvox), std::make_tuple(true, false, polyvox_forward) +#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT + , std::make_tuple(false, true, polyvox_fade), std::make_tuple(true, true, polyvox_forward_fade) +#else + , std::make_tuple(false, true, polyvox), std::make_tuple(true, true, polyvox_forward) +#endif + }; + for (auto& key : keys) { + for (int i = 0; i < 2; ++i) { + bool wireframe = i != 0; - auto wireframeState = std::make_shared(); - wireframeState->setCullMode(gpu::State::CULL_BACK); - wireframeState->setDepthTest(true, true, gpu::LESS_EQUAL); - wireframeState->setFillMode(gpu::State::FILL_LINE); - PrepareStencil::testMaskDrawShape(*wireframeState); + auto state = std::make_shared(); + state->setCullMode(gpu::State::CULL_BACK); + state->setDepthTest(true, true, gpu::LESS_EQUAL); + PrepareStencil::testMaskDrawShape(*state); - // Two sets of pipelines: normal and fading - for (auto i = 0; i < 2; i++) { - gpu::ShaderPointer program = gpu::Shader::createProgram(programsIds[i]); - _pipelines[i] = gpu::Pipeline::create(program, state); - _wireframePipelines[i] = gpu::Pipeline::create(program, wireframeState); + if (wireframe) { + state->setFillMode(gpu::State::FILL_LINE); + } + + auto pipeline = gpu::Pipeline::create(gpu::Shader::createProgram(std::get<2>(key)), state); + if (std::get<1>(key)) { + _pipelines[std::make_tuple(std::get<0>(key), std::get<1>(key), wireframe)] = std::make_shared(pipeline, nullptr, nullptr, nullptr); + } else { + const auto& fadeEffect = DependencyManager::get(); + _pipelines[std::make_tuple(std::get<0>(key), std::get<1>(key), wireframe)] = std::make_shared(pipeline, nullptr, + fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter()); + } + } } } -#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT - if (key.isFaded()) { - const auto& fadeEffect = DependencyManager::get(); - if (key.isWireframe()) { - return std::make_shared(_wireframePipelines[1], nullptr, fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter()); - } else { - return std::make_shared(_pipelines[1], nullptr, fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter()); - } - } else { -#endif - if (key.isWireframe()) { - return std::make_shared(_wireframePipelines[0], nullptr, nullptr, nullptr); - } else { - return std::make_shared(_pipelines[0], nullptr, nullptr, nullptr); - } -#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT - } -#endif + return _pipelines[std::make_tuple(args->_renderMethod == Args::RenderMethod::FORWARD, key.isFaded(), key.isWireframe())]; } PolyVoxEntityRenderer::PolyVoxEntityRenderer(const EntityItemPointer& entity) : Parent(entity) { diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 977a039e5b..38b93640ad 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -17,10 +17,6 @@ #include "RenderPipelines.h" -//#define SHAPE_ENTITY_USE_FADE_EFFECT -#ifdef SHAPE_ENTITY_USE_FADE_EFFECT -#include -#endif using namespace render; using namespace render::entities; @@ -269,12 +265,8 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { } else if (pipelineType == Pipeline::SIMPLE) { // FIXME, support instanced multi-shape rendering using multidraw indirect outColor.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; - render::ShapePipelinePointer pipeline; - if (renderLayer == RenderLayer::WORLD && args->_renderMethod != Args::RenderMethod::FORWARD) { - pipeline = outColor.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline(); - } else { - pipeline = outColor.a < 1.0f ? geometryCache->getForwardTransparentShapePipeline() : geometryCache->getForwardOpaqueShapePipeline(); - } + render::ShapePipelinePointer pipeline = geometryCache->getShapePipelinePointer(outColor.a < 1.0f, false, + renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD); if (render::ShapeKey(args->_globalShapeKey).isWireframe() || primitiveMode == PrimitiveMode::LINES) { geometryCache->renderWireShapeInstance(args, batch, geometryShape, outColor, pipeline); } else { diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index a281c1d097..0ead1de71a 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -25,8 +25,7 @@ using namespace render; using namespace render::entities; static const int FIXED_FONT_POINT_SIZE = 40; -const int FIXED_FONT_SCALING_RATIO = FIXED_FONT_POINT_SIZE * 92.0f; // Determined through experimentation to fit font to line - // height. +const int FIXED_FONT_SCALING_RATIO = FIXED_FONT_POINT_SIZE * 92.0f; // Determined through experimentation to fit font to line height. const float LINE_SCALE_RATIO = 1.2f; TextEntityRenderer::TextEntityRenderer(const EntityItemPointer& entity) : @@ -46,7 +45,13 @@ TextEntityRenderer::~TextEntityRenderer() { } bool TextEntityRenderer::isTransparent() const { - return Parent::isTransparent() || _textAlpha < 1.0f || _backgroundAlpha < 1.0f || _pulseProperties.getAlphaMode() != PulseMode::NONE; + return Parent::isTransparent() || _backgroundAlpha < 1.0f || _pulseProperties.getAlphaMode() != PulseMode::NONE; +} + +bool TextEntityRenderer::isTextTransparent() const { + return resultWithReadLock([&] { + return Parent::isTransparent() || _textAlpha < 1.0f || _pulseProperties.getAlphaMode() != PulseMode::NONE; + }); } Item::Bound TextEntityRenderer::getBound() { @@ -60,17 +65,33 @@ Item::Bound TextEntityRenderer::getBound() { return bound; } +ItemKey TextEntityRenderer::getKey() { + return ItemKey::Builder(Parent::getKey()).withMetaCullGroup(); +} + ShapeKey TextEntityRenderer::getShapeKey() { - auto builder = render::ShapeKey::Builder().withOwnPipeline(); + auto builder = render::ShapeKey::Builder().withoutCullFace(); if (isTransparent()) { builder.withTranslucent(); } + if (_unlit) { + builder.withUnlit(); + } if (_primitiveMode == PrimitiveMode::LINES) { builder.withWireframe(); } return builder.build(); } +uint32_t TextEntityRenderer::metaFetchMetaSubItems(ItemIDs& subItems) const { + auto parentSubs = Parent::metaFetchMetaSubItems(subItems); + if (Item::isValidID(_textRenderID)) { + subItems.emplace_back(_textRenderID); + return parentSubs + 1; + } + return parentSubs; +} + bool TextEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const { if (_text != entity->getText()) { return true; @@ -120,6 +141,10 @@ bool TextEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoint return true; } + if (_unlit != entity->getUnlit()) { + return true; + } + if (_pulseProperties != entity->getPulseProperties()) { return true; } @@ -134,6 +159,7 @@ void TextEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scen _dimensions = entity->getScaledDimensions(); updateModelTransformAndBound(); _renderTransform = getModelTransform(); + _renderTransform.postScale(_dimensions); }); }); } @@ -152,66 +178,53 @@ void TextEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointe _rightMargin = entity->getRightMargin(); _topMargin = entity->getTopMargin(); _bottomMargin = entity->getBottomMargin(); + _unlit = entity->getUnlit(); + updateTextRenderItem(); }); } void TextEntityRenderer::doRender(RenderArgs* args) { PerformanceTimer perfTimer("RenderableTextEntityItem::render"); - - glm::vec4 textColor; - glm::vec4 backgroundColor; - Transform modelTransform; - glm::vec3 dimensions; - BillboardMode billboardMode; - bool forward; - withReadLock([&] { - modelTransform = _renderTransform; - dimensions = _dimensions; - billboardMode = _billboardMode; - - float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; - textColor = glm::vec4(_textColor, fadeRatio * _textAlpha); - textColor = EntityRenderer::calculatePulseColor(textColor, _pulseProperties, _created); - backgroundColor = glm::vec4(_backgroundColor, fadeRatio * _backgroundAlpha); - backgroundColor = EntityRenderer::calculatePulseColor(backgroundColor, _pulseProperties, _created); - forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == render::Args::FORWARD; - }); - - // Render background - static const float SLIGHTLY_BEHIND = -0.005f; - glm::vec3 minCorner = glm::vec3(0.0f, -dimensions.y, SLIGHTLY_BEHIND); - glm::vec3 maxCorner = glm::vec3(dimensions.x, 0.0f, SLIGHTLY_BEHIND); - - // Batch render calls Q_ASSERT(args->_batch); gpu::Batch& batch = *args->_batch; - // FIXME: we need to find a better way of rendering text so we don't have to do this - if (forward) { - DependencyManager::get()->setupKeyLightBatch(args, batch); + glm::vec4 backgroundColor; + Transform modelTransform; + BillboardMode billboardMode; + PrimitiveMode primitiveMode; + RenderLayer renderLayer; + withReadLock([&] { + modelTransform = _renderTransform; + billboardMode = _billboardMode; + primitiveMode = _primitiveMode; + renderLayer = _renderLayer; + + float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; + backgroundColor = glm::vec4(_backgroundColor, fadeRatio * _backgroundAlpha); + backgroundColor = EntityRenderer::calculatePulseColor(backgroundColor, _pulseProperties, _created); + }); + + if (backgroundColor.a <= 0.0f) { + return; } - auto transformToTopLeft = modelTransform; - transformToTopLeft.setRotation(EntityItem::getBillboardRotation(transformToTopLeft.getTranslation(), transformToTopLeft.getRotation(), billboardMode, args->getViewFrustum().getPosition())); - transformToTopLeft.postTranslate(dimensions * glm::vec3(-0.5f, 0.5f, 0.0f)); // Go to the top left - transformToTopLeft.setScale(1.0f); // Use a scale of one so that the text is not deformed + modelTransform.setRotation(EntityItem::getBillboardRotation(modelTransform.getTranslation(), modelTransform.getRotation(), billboardMode, args->getViewFrustum().getPosition())); + batch.setModelTransform(modelTransform); - if (backgroundColor.a > 0.0f) { - batch.setModelTransform(transformToTopLeft); - auto geometryCache = DependencyManager::get(); - geometryCache->bindSimpleProgram(batch, false, backgroundColor.a < 1.0f, false, false, false, true, forward); - geometryCache->renderQuad(batch, minCorner, maxCorner, backgroundColor, _geometryID); - } + auto geometryCache = DependencyManager::get(); + // FIXME: we want to use instanced rendering here, but if textAlpha < 1 and backgroundAlpha < 1, the transparency sorting will be wrong + //render::ShapePipelinePointer pipeline = geometryCache->getShapePipelinePointer(backgroundColor.a < 1.0f, _unlit, + // renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD); + //if (render::ShapeKey(args->_globalShapeKey).isWireframe() || primitiveMode == PrimitiveMode::LINES) { + // geometryCache->renderWireShapeInstance(args, batch, GeometryCache::Quad, backgroundColor, pipeline); + //} else { + // geometryCache->renderSolidShapeInstance(args, batch, GeometryCache::Quad, backgroundColor, pipeline); + //} - if (textColor.a > 0.0f) { - // FIXME: Factor out textRenderer so that text parts can be grouped by pipeline for a gpu performance increase. - float scale = _lineHeight / _textRenderer->getFontSize(); - transformToTopLeft.setScale(scale); // Scale to have the correct line height - batch.setModelTransform(transformToTopLeft); + geometryCache->renderQuad(batch, glm::vec2(-0.5), glm::vec2(0.5), backgroundColor, _geometryID); - glm::vec2 bounds = glm::vec2(dimensions.x - (_leftMargin + _rightMargin), dimensions.y - (_topMargin + _bottomMargin)); - _textRenderer->draw(batch, _leftMargin / scale, -_topMargin / scale, _text, textColor, bounds / scale, forward); - } + const int TRIANBLES_PER_QUAD = 2; + args->_details._trianglesRendered += TRIANBLES_PER_QUAD; } QSizeF TextEntityRenderer::textSize(const QString& text) const { @@ -222,4 +235,175 @@ QSizeF TextEntityRenderer::textSize(const QString& text) const { float pointToWorldScale = (maxHeight / FIXED_FONT_SCALING_RATIO) * _lineHeight; return QSizeF(extents.x, extents.y) * pointToWorldScale; -} \ No newline at end of file +} + +void TextEntityRenderer::onAddToSceneTyped(const TypedEntityPointer& entity) { + Parent::onAddToSceneTyped(entity); + _textPayload = std::make_shared(entity->getID(), _textRenderer); + _textRenderID = AbstractViewStateInterface::instance()->getMain3DScene()->allocateID(); + auto renderPayload = std::make_shared(_textPayload); + render::Transaction transaction; + transaction.resetItem(_textRenderID, renderPayload); + AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction); +} + +void TextEntityRenderer::onRemoveFromSceneTyped(const TypedEntityPointer& entity) { + Parent::onRemoveFromSceneTyped(entity); + render::Transaction transaction; + transaction.removeItem(_textRenderID); + AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction); + _textPayload.reset(); +} + +void TextEntityRenderer::updateTextRenderItem() const { + render::Transaction transaction; + transaction.updateItem(_textRenderID); + AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction); +} + +entities::TextPayload::TextPayload(const QUuid& entityID, const std::weak_ptr& textRenderer) : + _entityID(entityID), _textRenderer(textRenderer) { + auto geometryCache = DependencyManager::get(); + if (geometryCache) { + _geometryID = geometryCache->allocateID(); + } +} + +entities::TextPayload::~TextPayload() { + auto geometryCache = DependencyManager::get(); + if (_geometryID && geometryCache) { + geometryCache->releaseID(_geometryID); + } +} + +ItemKey entities::TextPayload::getKey() const { + auto entityTreeRenderer = DependencyManager::get(); + if (entityTreeRenderer) { + auto renderable = entityTreeRenderer->renderableForEntityId(_entityID); + if (renderable) { + auto textRenderable = std::static_pointer_cast(renderable); + return ItemKey::Builder(textRenderable->getKey()).withoutMetaCullGroup().withSubMetaCulled(); + } + } + return ItemKey::Builder::opaqueShape(); +} + +Item::Bound entities::TextPayload::getBound() const { + auto entityTreeRenderer = DependencyManager::get(); + if (entityTreeRenderer) { + auto renderable = entityTreeRenderer->renderableForEntityId(_entityID); + if (renderable) { + return std::static_pointer_cast(renderable)->getBound(); + } + } + return Item::Bound(); +} + +ShapeKey entities::TextPayload::getShapeKey() const { + auto entityTreeRenderer = DependencyManager::get(); + if (entityTreeRenderer) { + auto renderable = entityTreeRenderer->renderableForEntityId(_entityID); + if (renderable) { + auto textRenderable = std::static_pointer_cast(renderable); + + auto builder = render::ShapeKey::Builder().withOwnPipeline(); + if (textRenderable->isTextTransparent()) { + builder.withTranslucent(); + } + if (textRenderable->_unlit) { + builder.withUnlit(); + } + if (textRenderable->_primitiveMode == PrimitiveMode::LINES) { + builder.withWireframe(); + } + return builder.build(); + } + } + return ShapeKey::Builder::invalid(); +} + +void entities::TextPayload::render(RenderArgs* args) { + PerformanceTimer perfTimer("TextPayload::render"); + Q_ASSERT(args->_batch); + gpu::Batch& batch = *args->_batch; + + auto textRenderer = _textRenderer.lock(); + if (!textRenderer) { + return; + } + + auto entityTreeRenderer = DependencyManager::get(); + if (!entityTreeRenderer) { + return; + } + auto renderable = entityTreeRenderer->renderableForEntityId(_entityID); + if (!renderable) { + return; + } + auto textRenderable = std::static_pointer_cast(renderable); + + glm::vec4 textColor; + Transform modelTransform; + BillboardMode billboardMode; + float lineHeight, leftMargin, rightMargin, topMargin, bottomMargin; + QString text; + glm::vec3 dimensions; + bool forward; + textRenderable->withReadLock([&] { + modelTransform = textRenderable->_renderTransform; + billboardMode = textRenderable->_billboardMode; + lineHeight = textRenderable->_lineHeight; + leftMargin = textRenderable->_leftMargin; + rightMargin = textRenderable->_rightMargin; + topMargin = textRenderable->_topMargin; + bottomMargin = textRenderable->_bottomMargin; + text = textRenderable->_text; + dimensions = textRenderable->_dimensions; + + float fadeRatio = textRenderable->_isFading ? Interpolate::calculateFadeRatio(textRenderable->_fadeStartTime) : 1.0f; + textColor = glm::vec4(textRenderable->_textColor, fadeRatio * textRenderable->_textAlpha); + textColor = EntityRenderer::calculatePulseColor(textColor, textRenderable->_pulseProperties, textRenderable->_created); + forward = textRenderable->_renderLayer != RenderLayer::WORLD || args->_renderMethod == render::Args::FORWARD; + }); + + if (textColor.a <= 0.0f) { + return; + } + + modelTransform.setRotation(EntityItem::getBillboardRotation(modelTransform.getTranslation(), modelTransform.getRotation(), billboardMode, args->getViewFrustum().getPosition())); + + float scale = lineHeight / textRenderer->getFontSize(); + modelTransform.postTranslate(glm::vec3(-0.5, 0.5, 1.0f + EPSILON / dimensions.z)); + modelTransform.setScale(scale); + batch.setModelTransform(modelTransform); + + glm::vec2 bounds = glm::vec2(dimensions.x - (leftMargin + rightMargin), dimensions.y - (topMargin + bottomMargin)); + textRenderer->draw(batch, leftMargin / scale, -topMargin / scale, text, textColor, bounds / scale, textRenderable->_unlit, forward); +} + +namespace render { +template <> const ItemKey payloadGetKey(const TextPayload::Pointer& payload) { + if (payload) { + return payload->getKey(); + } + return ItemKey::Builder::opaqueShape(); +} + +template <> const Item::Bound payloadGetBound(const TextPayload::Pointer& payload) { + if (payload) { + return payload->getBound(); + } + return Item::Bound(); +} + +template <> const ShapeKey shapeGetShapeKey(const TextPayload::Pointer& payload) { + if (payload) { + return payload->getShapeKey(); + } + return ShapeKey::Builder::invalid(); +} + +template <> void payloadRender(const TextPayload::Pointer& payload, RenderArgs* args) { + return payload->render(args); +} +} diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.h b/libraries/entities-renderer/src/RenderableTextEntityItem.h index e0306375a0..c62851a876 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.h +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.h @@ -19,6 +19,8 @@ class TextRenderer3D; namespace render { namespace entities { +class TextPayload; + class TextEntityRenderer : public TypedEntityRenderer { using Parent = TypedEntityRenderer; using Pointer = std::shared_ptr; @@ -30,8 +32,14 @@ public: protected: bool isTransparent() const override; + bool isTextTransparent() const; Item::Bound getBound() override; ShapeKey getShapeKey() override; + ItemKey getKey() override; + virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) const override; + + void onAddToSceneTyped(const TypedEntityPointer& entity) override; + void onRemoveFromSceneTyped(const TypedEntityPointer& entity) override; private: virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override; @@ -39,7 +47,6 @@ private: virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override; virtual void doRender(RenderArgs* args) override; - int _geometryID{ 0 }; std::shared_ptr _textRenderer; PulsePropertyGroup _pulseProperties; @@ -50,6 +57,7 @@ private: float _textAlpha; glm::vec3 _backgroundColor; float _backgroundAlpha; + bool _unlit; float _leftMargin; float _rightMargin; @@ -58,8 +66,44 @@ private: BillboardMode _billboardMode; glm::vec3 _dimensions; + + int _geometryID { 0 }; + + std::shared_ptr _textPayload; + render::ItemID _textRenderID; + void updateTextRenderItem() const; + + friend class render::entities::TextPayload; +}; + +class TextPayload { +public: + TextPayload() = default; + TextPayload(const QUuid& entityID, const std::weak_ptr& textRenderer); + ~TextPayload(); + + typedef render::Payload Payload; + typedef Payload::DataPointer Pointer; + + ItemKey getKey() const; + Item::Bound getBound() const; + ShapeKey getShapeKey() const; + void render(RenderArgs* args); + +protected: + QUuid _entityID; + std::weak_ptr _textRenderer; + + int _geometryID { 0 }; }; } } +namespace render { + template <> const ItemKey payloadGetKey(const entities::TextPayload::Pointer& payload); + template <> const Item::Bound payloadGetBound(const entities::TextPayload::Pointer& payload); + template <> const ShapeKey shapeGetShapeKey(const entities::TextPayload::Pointer& payload); + template <> void payloadRender(const entities::TextPayload::Pointer& payload, RenderArgs* args); +} + #endif // hifi_RenderableTextEntityItem_h diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index bb3e99157e..00be4a2f7d 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -315,12 +315,19 @@ void WebEntityRenderer::doRender(RenderArgs* args) { gpu::Batch& batch = *args->_batch; glm::vec4 color; Transform transform; + bool forward; withReadLock([&] { float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; color = glm::vec4(toGlm(_color), _alpha * fadeRatio); color = EntityRenderer::calculatePulseColor(color, _pulseProperties, _created); transform = _renderTransform; + forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == render::Args::FORWARD; }); + + if (color.a == 0.0f) { + return; + } + batch.setResourceTexture(0, _texture); transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); @@ -328,7 +335,7 @@ void WebEntityRenderer::doRender(RenderArgs* args) { // Turn off jitter for these entities batch.pushProjectionJitter(); - DependencyManager::get()->bindWebBrowserProgram(batch, color.a < OPAQUE_ALPHA_THRESHOLD); + DependencyManager::get()->bindWebBrowserProgram(batch, color.a < OPAQUE_ALPHA_THRESHOLD, forward); DependencyManager::get()->renderQuad(batch, topLeft, bottomRight, texMin, texMax, color, _geometryId); batch.popProjectionJitter(); batch.setResourceTexture(0, nullptr); diff --git a/libraries/entities-renderer/src/entities-renderer/paintStroke.slp b/libraries/entities-renderer/src/entities-renderer/paintStroke.slp index e69de29bb2..e283f4edcb 100644 --- a/libraries/entities-renderer/src/entities-renderer/paintStroke.slp +++ b/libraries/entities-renderer/src/entities-renderer/paintStroke.slp @@ -0,0 +1 @@ +DEFINES forward \ No newline at end of file diff --git a/libraries/entities-renderer/src/entities-renderer/paintStroke_forward.slp b/libraries/entities-renderer/src/entities-renderer/paintStroke_forward.slp deleted file mode 100644 index 4d49e0d3a4..0000000000 --- a/libraries/entities-renderer/src/entities-renderer/paintStroke_forward.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX paintStroke \ No newline at end of file diff --git a/libraries/entities-renderer/src/entities-renderer/polyvox.slp b/libraries/entities-renderer/src/entities-renderer/polyvox.slp index e69de29bb2..82853b2a91 100644 --- a/libraries/entities-renderer/src/entities-renderer/polyvox.slp +++ b/libraries/entities-renderer/src/entities-renderer/polyvox.slp @@ -0,0 +1 @@ +DEFINES (shadow fade)/forward \ No newline at end of file diff --git a/libraries/entities-renderer/src/entities-renderer/polyvox_fade.slp b/libraries/entities-renderer/src/entities-renderer/polyvox_fade.slp deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/libraries/entities-renderer/src/paintStroke.slf b/libraries/entities-renderer/src/paintStroke.slf index 6ea088751f..837291efe6 100644 --- a/libraries/entities-renderer/src/paintStroke.slf +++ b/libraries/entities-renderer/src/paintStroke.slf @@ -1,10 +1,8 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> +// <$_SCRIBE_FILENAME$> // Generated on <$_SCRIBE_DATE$> // -// paintStroke.frag -// fragment shader -// // Created by Eric Levin on 8/10/2015 // Copyright 2015 High Fidelity, Inc. // @@ -12,29 +10,32 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include DeferredBufferWrite.slh@> +<@if not HIFI_USE_FORWARD@> + <@include DeferredBufferWrite.slh@> +<@else@> + layout(location=0) out vec4 _fragColor0; +<@endif@> <@include paintStroke.slh@> <$declarePolyLineBuffers()$> LAYOUT(binding=0) uniform sampler2D _texture; -layout(location=0) in vec3 _normalWS; +<@if not HIFI_USE_FORWARD@> + layout(location=0) in vec3 _normalWS; +<@endif@> layout(location=1) in vec2 _texCoord; layout(location=2) in vec4 _color; layout(location=3) in float _distanceFromCenter; void main(void) { vec4 texel = texture(_texture, _texCoord); - int frontCondition = 1 - 2 * int(gl_FrontFacing); - vec3 color = _color.rgb * texel.rgb; - float alpha = texel.a * _color.a; + texel *= _color; + texel.a *= mix(1.0, pow(1.0 - abs(_distanceFromCenter), 10.0), _polylineData.faceCameraGlow.y); - alpha *= mix(1.0, pow(1.0 - abs(_distanceFromCenter), 10.0), _polylineData.faceCameraGlow.y); - - packDeferredFragmentTranslucent( - float(frontCondition) * _normalWS, - alpha, - color, - DEFAULT_ROUGHNESS); +<@if not HIFI_USE_FORWARD@> + packDeferredFragmentTranslucent((2.0 * float(gl_FrontFacing) - 1.0) * _normalWS, texel.a, texel.rgb, DEFAULT_ROUGHNESS); +<@else@> + _fragColor0 = texel; +<@endif@> } diff --git a/libraries/entities-renderer/src/paintStroke.slv b/libraries/entities-renderer/src/paintStroke.slv index f591370186..9a44223dd4 100644 --- a/libraries/entities-renderer/src/paintStroke.slv +++ b/libraries/entities-renderer/src/paintStroke.slv @@ -1,10 +1,8 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> +// <$_SCRIBE_FILENAME$> // Generated on <$_SCRIBE_DATE$> // -// paintStroke.vert -// vertex shader -// // Created by Eric Levin on 7/20/15. // Copyright 2014 High Fidelity, Inc. // @@ -20,7 +18,9 @@ <@include paintStroke.slh@> <$declarePolyLineBuffers()$> -layout(location=0) out vec3 _normalWS; +<@if not HIFI_USE_FORWARD@> + layout(location=0) out vec3 _normalWS; +<@endif@> layout(location=1) out vec2 _texCoord; layout(location=2) out vec4 _color; layout(location=3) out float _distanceFromCenter; @@ -50,11 +50,15 @@ void main(void) { vec3 binormalEye = normalize(cross(normalEye, tangentEye)); posEye.xyz += _distanceFromCenter * vertex.binormalAndHalfWidth.w * binormalEye; <$transformEyeToClipPos(cam, posEye, gl_Position)$> +<@if not HIFI_USE_FORWARD@> <$transformEyeToWorldDir(cam, normalEye, _normalWS)$> +<@endif@> } else { vec3 normal = vertex.normal.xyz; position.xyz += _distanceFromCenter * vertex.binormalAndHalfWidth.w * binormal; <$transformModelToClipPos(cam, obj, position, gl_Position)$> +<@if not HIFI_USE_FORWARD@> <$transformModelToWorldDir(cam, obj, normal, _normalWS)$> +<@endif@> } } \ No newline at end of file diff --git a/libraries/entities-renderer/src/paintStroke_forward.slf b/libraries/entities-renderer/src/paintStroke_forward.slf deleted file mode 100644 index b949332826..0000000000 --- a/libraries/entities-renderer/src/paintStroke_forward.slf +++ /dev/null @@ -1,35 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// paintStroke.frag -// fragment shader -// -// Created by Eric Levin on 8/10/2015 -// Copyright 2015 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 paintStroke.slh@> -<$declarePolyLineBuffers()$> - -LAYOUT(binding=0) uniform sampler2D _texture; - -layout(location=0) in vec3 _normalWS; -layout(location=1) in vec2 _texCoord; -layout(location=2) in vec4 _color; -layout(location=3) in float _distanceFromCenter; -layout(location=0) out vec4 _fragColor0; - -void main(void) { - vec4 texel = texture(_texture, _texCoord); - int frontCondition = 1 - 2 * int(gl_FrontFacing); - vec3 color = _color.rgb * texel.rgb; - float alpha = texel.a * _color.a; - - alpha *= mix(1.0, pow(1.0 - abs(_distanceFromCenter), 10.0), _polylineData.faceCameraGlow.y); - - _fragColor0 = vec4(color, alpha); -} diff --git a/libraries/entities-renderer/src/polyvox.slf b/libraries/entities-renderer/src/polyvox.slf index 6b1aa25a25..3456823081 100644 --- a/libraries/entities-renderer/src/polyvox.slf +++ b/libraries/entities-renderer/src/polyvox.slf @@ -1,8 +1,7 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> +// <$_SCRIBE_FILENAME$> // Generated on <$_SCRIBE_DATE$> -// polyvox.frag -// fragment shader // // Created by Seth Alves on 2015-8-3 // Copyright 2015 High Fidelity, Inc. @@ -11,51 +10,111 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include graphics/Material.slh@> -<@include DeferredBufferWrite.slh@> -<@include render-utils/ShaderConstants.h@> -<@include entities-renderer/ShaderConstants.h@> +<@if HIFI_USE_FADE@> + <@include Fade.slh@> + <$declareFadeFragment()$> -layout(location=RENDER_UTILS_ATTR_NORMAL_MS) in vec3 _normal; -layout(location=RENDER_UTILS_ATTR_POSITION_MS) in vec4 _position; -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _worldPosition; + layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; +<@endif@> -LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_XMAP) uniform sampler2D xMap; -LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_YMAP) uniform sampler2D yMap; -LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_ZMAP) uniform sampler2D zMap; +<@if not HIFI_USE_SHADOW@> + <@include graphics/Material.slh@> + <@include render-utils/ShaderConstants.h@> + <@include entities-renderer/ShaderConstants.h@> -struct PolyvoxParams { - vec4 voxelVolumeSize; -}; + <@if not HIFI_USE_FORWARD@> + <@include DeferredBufferWrite.slh@> + <@else@> + <@include DefaultMaterials.slh@> -LAYOUT(binding=0) uniform polyvoxParamsBuffer { - PolyvoxParams params; -}; + <@include GlobalLight.slh@> + <$declareEvalSkyboxGlobalColor(_SCRIBE_NULL, HIFI_USE_FORWARD)$> + + <@include gpu/Transform.slh@> + <$declareStandardCameraTransform()$> + <@endif@> + + <@if HIFI_USE_FORWARD@> + layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; + <@endif@> + layout(location=RENDER_UTILS_ATTR_POSITION_MS) in vec3 _positionMS; + layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; + + LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_XMAP) uniform sampler2D xMap; + LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_YMAP) uniform sampler2D yMap; + LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_ZMAP) uniform sampler2D zMap; + + struct PolyvoxParams { + vec4 voxelVolumeSize; + }; + + LAYOUT(binding=0) uniform polyvoxParamsBuffer { + PolyvoxParams params; + }; +<@endif@> + +<@if HIFI_USE_SHADOW or HIFI_USE_FORWARD@> + layout(location=0) out vec4 _fragColor0; +<@endif@> void main(void) { - vec3 worldNormal = cross(dFdy(_worldPosition.xyz), dFdx(_worldPosition.xyz)); - worldNormal = normalize(worldNormal); +<@if HIFI_USE_FADE@> + <@if not HIFI_USE_SHADOW@> + vec3 fadeEmissive; + FadeObjectParams fadeParams; + <$fetchFadeObjectParams(fadeParams)$> + applyFade(fadeParams, _positionWS.xyz, fadeEmissive); + <@else@> + FadeObjectParams fadeParams; + <$fetchFadeObjectParams(fadeParams)$> + applyFadeClip(fadeParams, _positionWS.xyz); + <@endif@> +<@endif@> - float inPositionX = (_worldPosition.x - 0.5) / params.voxelVolumeSize.x; - float inPositionY = (_worldPosition.y - 0.5) / params.voxelVolumeSize.y; - float inPositionZ = (_worldPosition.z - 0.5) / params.voxelVolumeSize.z; +<@if not HIFI_USE_SHADOW@> + float inPositionX = (_positionMS.x - 0.5) / params.voxelVolumeSize.x; + float inPositionY = (_positionMS.y - 0.5) / params.voxelVolumeSize.y; + float inPositionZ = (_positionMS.z - 0.5) / params.voxelVolumeSize.z; vec4 xyDiffuse = texture(xMap, vec2(-inPositionX, -inPositionY)); vec4 xzDiffuse = texture(yMap, vec2(-inPositionX, inPositionZ)); vec4 yzDiffuse = texture(zMap, vec2(inPositionZ, -inPositionY)); - vec3 xyDiffuseScaled = xyDiffuse.rgb * abs(worldNormal.z); - vec3 xzDiffuseScaled = xzDiffuse.rgb * abs(worldNormal.y); - vec3 yzDiffuseScaled = yzDiffuse.rgb * abs(worldNormal.x); - vec4 diffuse = vec4(xyDiffuseScaled + xzDiffuseScaled + yzDiffuseScaled, 1.0); + vec3 normalMS = normalize(cross(dFdy(_positionMS.xyz), dFdx(_positionMS.xyz))); + vec3 xyDiffuseScaled = xyDiffuse.rgb * abs(normalMS.z); + vec3 xzDiffuseScaled = xzDiffuse.rgb * abs(normalMS.y); + vec3 yzDiffuseScaled = yzDiffuse.rgb * abs(normalMS.x); + vec3 diffuse = vec3(xyDiffuseScaled + xzDiffuseScaled + yzDiffuseScaled); - packDeferredFragment( - _normal, - 1.0, - vec3(diffuse), - DEFAULT_ROUGHNESS, - DEFAULT_METALLIC, - DEFAULT_EMISSIVE, - DEFAULT_OCCLUSION, - DEFAULT_SCATTERING); + <@if not HIFI_USE_FORWARD@> + packDeferredFragment( + normalize(_normalWS), + 1.0, + diffuse, + DEFAULT_ROUGHNESS, + DEFAULT_METALLIC, + DEFAULT_EMISSIVE + <@if HIFI_USE_FADE@> + + fadeEmissive + <@endif@> + , + DEFAULT_OCCLUSION, + DEFAULT_SCATTERING); + <@else@> + TransformCamera cam = getTransformCamera(); + _fragColor0 = vec4(evalSkyboxGlobalColor( + cam._viewInverse, + 1.0, + DEFAULT_OCCLUSION, + _positionES.xyz, + normalize(_normalWS), + diffuse, + DEFAULT_FRESNEL, + DEFAULT_METALLIC, + DEFAULT_ROUGHNESS), + 1.0); + <@endif@> +<@else@> + _fragColor0 = vec4(1.0); +<@endif@> } diff --git a/libraries/entities-renderer/src/polyvox.slv b/libraries/entities-renderer/src/polyvox.slv index d17974c994..34547cef1a 100644 --- a/libraries/entities-renderer/src/polyvox.slv +++ b/libraries/entities-renderer/src/polyvox.slv @@ -1,8 +1,7 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> +// <$_SCRIBE_FILENAME$> // Generated on <$_SCRIBE_DATE$> -// polyvox.vert -// vertex shader // // Copyright 2015 High Fidelity, Inc. // @@ -11,20 +10,39 @@ // <@include gpu/Inputs.slh@> -<@include gpu/Transform.slh@> <@include render-utils/ShaderConstants.h@> +<@include gpu/Transform.slh@> <$declareStandardTransform()$> -layout(location=RENDER_UTILS_ATTR_POSITION_MS) out vec4 _position; -layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _worldPosition; -layout(location=RENDER_UTILS_ATTR_NORMAL_MS) out vec3 _normal; +<@if HIFI_USE_FADE@> + layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS; +<@endif@> +<@if not HIFI_USE_SHADOW@> + <@if HIFI_USE_FORWARD@> + layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; + <@endif@> + layout(location=RENDER_UTILS_ATTR_POSITION_MS) out vec3 _positionMS; + layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; +<@endif@> void main(void) { - // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$> - <$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$> - _worldPosition = inPosition; + +<@if HIFI_USE_SHADOW@> + <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> +<@else@> + <@if not HIFI_USE_FORWARD@> + <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> + <@else@> + <$transformModelToEyeAndClipPos(cam, obj, inPosition, _positionES, gl_Position)$> + <@endif@> + + <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normalWS)$> + _positionMS = inPosition.xyz; +<@endif@> +<@if HIFI_USE_FADE@> + <$transformModelToWorldPos(obj, inPosition, _positionWS)$> +<@endif@> } diff --git a/libraries/entities-renderer/src/polyvox_fade.slf b/libraries/entities-renderer/src/polyvox_fade.slf deleted file mode 100644 index ae2e05c3dc..0000000000 --- a/libraries/entities-renderer/src/polyvox_fade.slf +++ /dev/null @@ -1,73 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// polyvox_fade.frag -// fragment shader -// -// Created by Olivier Prat on 2017-06-08 -// 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 graphics/Material.slh@> -<@include DeferredBufferWrite.slh@> -<@include render-utils/ShaderConstants.h@> -<@include entities-renderer/ShaderConstants.h@> - -<@include Fade.slh@> - -layout(location=RENDER_UTILS_ATTR_NORMAL_MS) in vec3 _normal; -layout(location=RENDER_UTILS_ATTR_POSITION_MS) in vec4 _position; -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _worldPosition; -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _worldFadePosition; - -LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_XMAP) uniform sampler2D xMap; -LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_YMAP) uniform sampler2D yMap; -LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_ZMAP) uniform sampler2D zMap; - -struct PolyvoxParams { - vec4 voxelVolumeSize; -}; - -LAYOUT(binding=0) uniform polyvoxParamsBuffer { - PolyvoxParams params; -}; - -// Declare after all samplers to prevent sampler location mix up with voxel shading (sampler locations are hardcoded in RenderablePolyVoxEntityItem) -<$declareFadeFragment()$> - -void main(void) { - vec3 emissive; - FadeObjectParams fadeParams; - - <$fetchFadeObjectParams(fadeParams)$> - applyFade(fadeParams, _worldFadePosition.xyz, emissive); - - vec3 worldNormal = cross(dFdy(_worldPosition.xyz), dFdx(_worldPosition.xyz)); - worldNormal = normalize(worldNormal); - - float inPositionX = (_worldPosition.x - 0.5) / params.voxelVolumeSize.x; - float inPositionY = (_worldPosition.y - 0.5) / params.voxelVolumeSize.y; - float inPositionZ = (_worldPosition.z - 0.5) / params.voxelVolumeSize.z; - - vec4 xyDiffuse = texture(xMap, vec2(-inPositionX, -inPositionY)); - vec4 xzDiffuse = texture(yMap, vec2(-inPositionX, inPositionZ)); - vec4 yzDiffuse = texture(zMap, vec2(inPositionZ, -inPositionY)); - - vec3 xyDiffuseScaled = xyDiffuse.rgb * abs(worldNormal.z); - vec3 xzDiffuseScaled = xzDiffuse.rgb * abs(worldNormal.y); - vec3 yzDiffuseScaled = yzDiffuse.rgb * abs(worldNormal.x); - vec4 diffuse = vec4(xyDiffuseScaled + xzDiffuseScaled + yzDiffuseScaled, 1.0); - - packDeferredFragment( - _normal, - 1.0, - vec3(diffuse), - DEFAULT_ROUGHNESS, - DEFAULT_METALLIC, - DEFAULT_EMISSIVE+emissive, - DEFAULT_OCCLUSION, - DEFAULT_SCATTERING); -} diff --git a/libraries/entities-renderer/src/polyvox_fade.slv b/libraries/entities-renderer/src/polyvox_fade.slv deleted file mode 100644 index 97b98f5840..0000000000 --- a/libraries/entities-renderer/src/polyvox_fade.slv +++ /dev/null @@ -1,33 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// polyvox_fade.vert -// vertex shader -// -// Created by Seth Alves on 2015-8-3 -// Copyright 2015 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 gpu/Inputs.slh@> -<@include gpu/Transform.slh@> -<@include render-utils/ShaderConstants.h@> - -<$declareStandardTransform()$> - -layout(location=RENDER_UTILS_ATTR_POSITION_MS) out vec4 _position; -layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _worldPosition; -layout(location=RENDER_UTILS_ATTR_NORMAL_MS) out vec3 _normal; -layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _worldFadePosition; - -void main(void) { - // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$> - <$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$> - <$transformModelToWorldPos(obj, inPosition, _worldFadePosition)$> - _worldPosition = inPosition; -} diff --git a/libraries/entities/src/AnimationPropertyGroup.cpp b/libraries/entities/src/AnimationPropertyGroup.cpp index 03cd3a0742..7f9225bd6c 100644 --- a/libraries/entities/src/AnimationPropertyGroup.cpp +++ b/libraries/entities/src/AnimationPropertyGroup.cpp @@ -57,10 +57,11 @@ bool operator!=(const AnimationPropertyGroup& a, const AnimationPropertyGroup& b * @property {number} firstFrame=0 - The first frame to play in the animation. * @property {number} lastFrame=100000 - The last frame to play in the animation. * @property {number} currentFrame=0 - The current frame being played in the animation. - * @property {boolean} running=false - If true then the animation should play. - * @property {boolean} loop=true - If true then the animation is continuously repeated in a loop. - * @property {boolean} hold=false - If true then the rotations and translations of the last frame played are - * maintained when the animation stops playing. + * @property {boolean} running=false - true if the animation should play, false if it shouldn't. + * @property {boolean} loop=true - true if the animation is continuously repeated in a loop, false if + * it isn't. + * @property {boolean} hold=false - true if the rotations and translations of the last frame played are + * maintained when the animation stops playing, false if they aren't. */ void AnimationPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const { COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_URL, Animation, animation, URL, url); diff --git a/libraries/entities/src/EntityDynamicInterface.cpp b/libraries/entities/src/EntityDynamicInterface.cpp index 4586b665ee..69d771db22 100644 --- a/libraries/entities/src/EntityDynamicInterface.cpp +++ b/libraries/entities/src/EntityDynamicInterface.cpp @@ -109,7 +109,7 @@ variables. These argument variables are used by the code which is run when bull * are disabled during the hold. * {@link Entities.ActionArguments-Hold} * "offset"Object action - * Moves an entity so that it is a set distance away from a target point. + * Moves an entity so that it is a defined distance away from a target point. * {@link Entities.ActionArguments-Offset} * "tractor"Object action * Moves and rotates an entity to a target position and orientation, optionally relative to another entity. diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 5b3bbb88ee..878d220c22 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -527,6 +527,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_RIGHT_MARGIN, rightMargin); CHECK_PROPERTY_CHANGE(PROP_TOP_MARGIN, topMargin); CHECK_PROPERTY_CHANGE(PROP_BOTTOM_MARGIN, bottomMargin); + CHECK_PROPERTY_CHANGE(PROP_UNLIT, unlit); // Zone changedProperties += _keyLight.getChangedProperties(); @@ -609,8 +610,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { /**jsdoc * Different entity types have different properties: some common to all entities (listed in the table) and some specific to - * each {@link Entities.EntityType|EntityType} (linked to below). The properties are accessed as an object of property names - * and values. + * each {@link Entities.EntityType|EntityType} (linked to below). * * @typedef {object} Entities.EntityProperties * @property {Uuid} id - The ID of the entity. Read-only. @@ -644,16 +644,17 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {Uuid} lastEditedBy - The session ID of the avatar or agent that most recently created or edited the entity. * Read-only. * - * @property {boolean} locked=false - Whether or not the entity can be edited or deleted. If true then the - * entity's properties other than locked cannot be changed, and the entity cannot be deleted. - * @property {boolean} visible=true - Whether or not the entity is rendered. If true then the entity is rendered. - * @property {boolean} canCastShadow=true - Whether or not the entity can cast a shadow. Currently applicable only to - * {@link Entities.EntityProperties-Model|Model} and {@link Entities.EntityProperties-Shape|Shape} entities. Shadows are - * cast if inside a {@link Entities.EntityProperties-Zone|Zone} entity with castShadows enabled in its - * keyLight property. + * @property {boolean} locked=false - true if properties other than locked cannot be changed and the + * entity cannot be deleted, false if all properties can be changed and the entity can be deleted. + * @property {boolean} visible=true - true if the entity is rendered, false if it isn't. + * @property {boolean} canCastShadow=true - true if the entity can cast a shadow, false if it can't. + * Currently applicable only to {@link Entities.EntityProperties-Model|Model} and + * {@link Entities.EntityProperties-Shape|Shape} entities. Shadows are cast if inside a + * {@link Entities.EntityProperties-Zone|Zone} entity with castShadows enabled in its keyLight + * property. * @property {boolean} isVisibleInSecondaryCamera=true - true if the entity is rendered in the secondary camera, * false if it isn't. - * @property {Entities.RenderLayer} renderLayer="world" - Which layer the entity renders in. + * @property {Entities.RenderLayer} renderLayer="world" - The layer that the entity renders in. * @property {Entities.PrimitiveMode} primitiveMode="solid" - How the entity's geometry is rendered. * @property {boolean} ignorePickIntersection=false - true if {@link Picks} and {@link RayPick} ignore the entity, * false if they don't. @@ -697,20 +698,20 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {number} friction=0.5 - How much an entity slows down when it's moving against another, range 0.0 * – 10.0. The higher the value, the more quickly it slows down. Examples: 0.1 for ice, * 0.9 for sandpaper. - * @property {number} density=1000 - The density of the entity in kg/m3, range 100 for balsa wood - * – 10000 for silver. The density is used in conjunction with the entity's bounding box volume to work - * out its mass in the application of physics. + * @property {number} density=1000 - The density of the entity in kg/m3, range 100 – + * 10000. Examples: 100 for balsa wood, 10000 for silver. The density is used in + * conjunction with the entity's bounding box volume to work out its mass in the application of physics. * - * @property {boolean} collisionless=false - Whether or not the entity should collide with items per its - * collisionMask property. If true then the entity does not collide. + * @property {boolean} collisionless=false - true if the entity shouldn't collide, false if it + * collides with items per its collisionMask property. * @property {boolean} ignoreForCollisions - Synonym for collisionless. * @property {CollisionMask} collisionMask=31 - What types of items the entity should collide with. * @property {string} collidesWith="static,dynamic,kinematic,myAvatar,otherAvatar," - Synonym for collisionMask, * in text format. * @property {string} collisionSoundURL="" - The sound that's played when the entity experiences a collision. Valid file * formats are per {@link SoundObject}. - * @property {boolean} dynamic=false - Whether or not the entity should be affected by collisions. If true then - * the entity's movement is affected by collisions. + * @property {boolean} dynamic=false - true if the entity's movement is affected by collisions, false + * if it isn't. * @property {boolean} collisionsWillMove - A synonym for dynamic. * * @property {string} href="" - A "hifi://" metaverse address that a user is teleported to when they click on the entity. @@ -732,8 +733,8 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * button beside the "script URL" field in properties tab of the Create app works. * @property {string} serverScripts="" - The URL of the server entity script, if any, that is attached to the entity. * - * @property {Uuid} parentID=Uuid.NULL - The ID of the entity or avatar that the entity is parented to. - * {@link Uuid(0)|Uuid.NULL} if the entity is not parented. + * @property {Uuid} parentID=Uuid.NULL - The ID of the entity or avatar that the entity is parented to. A value of + * {@link Uuid(0)|Uuid.NULL} is used if the entity is not parented. * @property {number} parentJointIndex=65535 - The joint of the entity or avatar that the entity is parented to. Use * 65535 or -1 to parent to the entity or avatar's position and orientation rather than a joint. * @property {Vec3} localPosition=0,0,0 - The position of the entity relative to its parent if the entity is parented, @@ -759,19 +760,19 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {string} actionData="" - Base-64 encoded compressed dump of the actions associated with the entity. This property * is typically not used in scripts directly; rather, functions that manipulate an entity's actions update it, e.g., * {@link Entities.addAction}. The size of this property increases with the number of actions. Because this property value - * has to fit within a High Fidelity datagram packet there is a limit to the number of actions that an entity can have, and + * has to fit within a High Fidelity datagram packet, there is a limit to the number of actions that an entity can have; * edits which would result in overflow are rejected. Read-only. * @property {Entities.RenderInfo} renderInfo - Information on the cost of rendering the entity. Currently information is only * provided for Model entities. Read-only. * - * @property {boolean} cloneable=false - If true then the domain or avatar entity can be cloned via - * {@link Entities.cloneEntity}. + * @property {boolean} cloneable=false - true if the domain or avatar entity can be cloned via + * {@link Entities.cloneEntity}, false if it can't be. * @property {number} cloneLifetime=300 - The entity lifetime for clones created from this entity. * @property {number} cloneLimit=0 - The total number of clones of this entity that can exist in the domain at any given time. - * @property {boolean} cloneDynamic=false - If true then clones created from this entity will have their - * dynamic property set to true. - * @property {boolean} cloneAvatarEntity=false - If true then clones created from this entity will be created as - * avatar entities. + * @property {boolean} cloneDynamic=false - true if clones created from this entity will have their + * dynamic property set to true, false if they won't. + * @property {boolean} cloneAvatarEntity=false - true if clones created from this entity will be created as + * avatar entities, false if they won't be. * @property {Uuid} cloneOriginID - The ID of the entity that this entity was cloned from. * * @property {Entities.Grab} grab - The entity's grab-related properties. @@ -833,8 +834,8 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {Color} color=255,255,255 - The color of the light emitted. * @property {number} intensity=1 - The brightness of the light. * @property {number} falloffRadius=0.1 - The distance from the light's center at which intensity is reduced by 25%. - * @property {boolean} isSpotlight=false - If true then the light is directional, emitting along the entity's - * local negative z-axis; otherwise, the light is a point light which emanates in all directions. + * @property {boolean} isSpotlight=false - true if the light is directional, emitting along the entity's + * local negative z-axis; false if the light is a point light which emanates in all directions. * @property {number} exponent=0 - Affects the softness of the spotlight beam: the higher the value the softer the beam. * @property {number} cutoff=1.57 - Affects the size of the spotlight beam: the higher the value the larger the beam. * @example Create a spotlight pointing at the ground. @@ -855,7 +856,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { /**jsdoc * The "Line" {@link Entities.EntityType|EntityType} draws thin, straight lines between a sequence of two or more * points. It has properties in addition to the common {@link Entities.EntityProperties|EntityProperties}. - *

Deprecated: Use PolyLines instead.

+ *

Deprecated: Use {@link Entities.EntityProperties-PolyLine|PolyLine} entities instead.

* * @typedef {object} Entities.EntityProperties-Line * @property {Vec3} dimensions=0.1,0.1,0.1 - The dimensions of the entity. Must be sufficient to contain all the @@ -904,7 +905,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * 0. * @property {string} parentMaterialName="0" - Selects the mesh part or parts within the parent to which to apply the material. * If in the format "mat::string", all mesh parts with material name "string" are replaced. - * If "all" then all mesh parts are replaced. + * If "all", then all mesh parts are replaced. * Otherwise the property value is parsed as an unsigned integer, specifying the mesh part index to modify. *

If the string represents an array (starts with "[" and ends with "]"), the string is split * at each "," and each element parsed as either a number or a string if it starts with "mat::". @@ -919,8 +920,9 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * { x: 0, y: 0 }{ x: 1, y: 1 }. * @property {Vec2} materialMappingScale=1,1 - How much to scale the material within the parent's UV-space. * @property {number} materialMappingRot=0 - How much to rotate the material within the parent's UV-space, in degrees. - * @property {boolean} materialRepeat=true - If true, the material repeats. If false, fragments - * outside of texCoord 0 – 1 will be discarded. Works in both "uv" and "projected" modes. + * @property {boolean} materialRepeat=true - true if the material repeats, false if it doesn't. If + * false, fragments outside of texCoord 0 – 1 will be discarded. Works in both "uv" and + * "projected" modes. * @example Color a sphere using a Material entity. * var entityID = Entities.addEntity({ * type: "Sphere", @@ -980,7 +982,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * model hasn't loaded. The array indexes are per {@link Entities.getJointIndex|getJointIndex}. Rotations are relative to * each joint's parent. *

Joint rotations can be set by {@link Entities.setLocalJointRotation|setLocalJointRotation} and similar functions, or - * by setting the value of this property. If you set a joint rotation using this property you also need to set the + * by setting the value of this property. If you set a joint rotation using this property, you also need to set the * corresponding jointRotationsSet value to true.

* @property {boolean[]} jointRotationsSet=[]] - true values for joints that have had rotations applied, * false otherwise; [] if none are applied or the model hasn't loaded. The array indexes are per @@ -994,10 +996,11 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {boolean[]} jointTranslationsSet=[]] - true values for joints that have had translations applied, * false otherwise; [] if none are applied or the model hasn't loaded. The array indexes are per * {@link Entities.getJointIndex|getJointIndex}. - * @property {boolean} relayParentJoints=false - If true and the entity is parented to an avatar, then the - * avatar's joint rotations are applied to the entity's joints. - * @property {boolean} groupCulled=false - If true, the mesh parts of the model are LOD culled as a group. - * If false, separate mesh parts will be LOD culled individually. + * @property {boolean} relayParentJoints=false - true if when the entity is parented to an avatar, the avatar's + * joint rotations are applied to the entity's joints; false if a parent avatar's joint rotations are not + * applied to the entity's joints. + * @property {boolean} groupCulled=false - true if the mesh parts of the model are LOD culled as a group, + * false if separate mesh parts are LOD culled individually. * * @example Rez a Vive tracker puck. * var entity = Entities.addEntity({ @@ -1033,8 +1036,8 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * – {x: 0, y: -8.8, z: 0}. * @property {Vec3} dimensions - The dimensions of the particle effect, i.e., a bounding box containing all the particles * during their lifetimes, assuming that emitterShouldTrail == false. Read-only. - * @property {boolean} emitterShouldTrail=false - If true then particles are "left behind" as the emitter moves, - * otherwise they stay within the entity's dimensions. + * @property {boolean} emitterShouldTrail=false - true if particles are "left behind" as the emitter moves, + * false if they stay within the entity's dimensions. * * @property {Quat} emitOrientation=-0.707,0,0,0.707 - The orientation of particle emission relative to the entity's axes. By * default, particles emit along the entity's local z-axis, and azimuthStart and azimuthFinish @@ -1105,8 +1108,8 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * 2 * Math.PI radians. For example, if particleSpin == Math.PI and * spinSpread == Math.PI / 2, each particle will have a rotation in the range Math.PI / 2 – * 3 * Math.PI / 2. - * @property {boolean} rotateWithEntity=false - true to make the particles' rotations relative to the entity's - * instantaneous rotation, false to make them relative to world coordinates. If true with + * @property {boolean} rotateWithEntity=false - true if the particles' rotations are relative to the entity's + * instantaneous rotation, false if they're relative to world coordinates. If true with * particleSpin == 0, the particles keep oriented per the entity's orientation. * * @example Create a ball of green smoke. @@ -1141,17 +1144,19 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {number[]} strokeWidths=[]] - The widths, in m, of the line at the linePoints. Must be specified in * order for the entity to render. * @property {Vec3[]} strokeColors=[]] - The base colors of each point, with values in the range 0.0,0.0,0.0 - * — 1.0,1.0,1.0. These colors are multiplied with the color of the texture. If there are more line + * – 1.0,1.0,1.0. These colors are multiplied with the color of the texture. If there are more line * points than stroke colors, the color property value is used for the remaining points. - *

Warning: The ordinate values are in the range 0.01.0.

+ *

Warning: The ordinate values are in the range 0.01.0.

* @property {Color} color=255,255,255 - Used as the color for each point if strokeColors doesn't have a value for * the point. * @property {string} textures="" - The URL of a JPG or PNG texture to use for the lines. If you want transparency, use PNG * format. - * @property {boolean} isUVModeStretch=true - If true, the texture is stretched to fill the whole line, otherwise - * the texture repeats along the line. - * @property {boolean} glow=false - If true, the opacity of the strokes drops off away from the line center. - * @property {boolean} faceCamera=false - If true, each line segment rotates to face the camera. + * @property {boolean} isUVModeStretch=true - true if the texture is stretched to fill the whole line, + * false if the texture repeats along the line. + * @property {boolean} glow=false - true if the opacity of the strokes drops off away from the line center, + * false if it doesn't. + * @property {boolean} faceCamera=false - true if each line segment rotates to face the camera, false + * if they don't. * @example Draw a textured "V". * var entity = Entities.addEntity({ * type: "PolyLine", @@ -1192,9 +1197,8 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * the PolyVox data. This property is typically not used in scripts directly; rather, functions that manipulate a PolyVox * entity update it.
* The size of this property increases with the size and complexity of the PolyVox entity, with the size depending on how - * the particular entity's voxels compress. Because this property value has to fit within a High Fidelity datagram packet - * there is a limit to the size and complexity of a PolyVox entity, and edits which would result in an overflow are - * rejected. + * the particular entity's voxels compress. Because this property value has to fit within a High Fidelity datagram packet, + * there is a limit to the size and complexity of a PolyVox entity; edits which would result in an overflow are rejected. * @property {Entities.PolyVoxSurfaceStyle} voxelSurfaceStyle=2 - The style of rendering the voxels' surface and how * neighboring PolyVox entities are joined. * @property {string} xTextureURL="" - The URL of the texture to map to surfaces perpendicular to the entity's local x-axis. @@ -1281,13 +1285,14 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {number} rightMargin=0.0 - The right margin, in meters. * @property {number} topMargin=0.0 - The top margin, in meters. * @property {number} bottomMargin=0.0 - The bottom margin, in meters. + * @property {boolean} unlit=false - true if the entity should be unaffected by lighting. Otherwise, the text + * is lit by the keylight and local lights. * @property {BillboardMode} billboardMode="none" - Whether the entity is billboarded to face the camera. - * @property {boolean} faceCamera - true if billboardMode is "yaw", otherwise - * false. Setting this property to false sets the billboardMode to - * "none". + * @property {boolean} faceCamera - true if billboardMode is "yaw", false + * if it isn't. Setting this property to false sets the billboardMode to "none". *

Deprecated: This property is deprecated and will be removed.

- * @property {boolean} isFacingAvatar - true if billboardMode is "full", otherwise - * false. Setting this property to false sets the billboardMode to + * @property {boolean} isFacingAvatar - true if billboardMode is "full", + * false if it isn't. Setting this property to false sets the billboardMode to * "none". *

Deprecated: This property is deprecated and will be removed.

* @example Create a text entity. @@ -1312,17 +1317,18 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {Vec3} dimensions=0.1,0.1,0.01 - The dimensions of the entity. * @property {string} sourceUrl="" - The URL of the web page to display. This value does not change as you or others navigate * on the Web entity. - * @property {Color} color=255,255,255 - The color of the web surface. + * @property {Color} color=255,255,255 - The color of the web surface. This color tints the web page displayed: the pixel + * colors on the web page are multiplied by the property color. For example, a value of + * { red: 255, green: 0, blue: 0 } lets only the red channel of pixels' colors through. * @property {number} alpha=1 - The opacity of the web surface. * @property {Entities.Pulse} pulse - Color and alpha pulse. *

Deprecated: This property is deprecated and will be removed.

* @property {BillboardMode} billboardMode="none" - Whether the entity is billboarded to face the camera. - * @property {boolean} faceCamera - true if billboardMode is "yaw", otherwise - * false. Setting this property to false sets the billboardMode to - * "none". + * @property {boolean} faceCamera - true if billboardMode is "yaw", false + * if it isn't. Setting this property to false sets the billboardMode to "none". *

Deprecated: This property is deprecated and will be removed.

- * @property {boolean} isFacingAvatar - true if billboardMode is "full", otherwise - * false. Setting this property to false sets the billboardMode to + * @property {boolean} isFacingAvatar - true if billboardMode is "full", + * false if it isn't. Setting this property to false sets the billboardMode to * "none". *

Deprecated: This property is deprecated and will be removed.

* @property {number} dpi=30 - The resolution to display the page at, in dots per inch. If you convert this to dots per meter @@ -1331,8 +1337,8 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {string} scriptURL="" - The URL of a JavaScript file to inject into the web page. * @property {number} maxFPS=10 - The maximum update rate for the web content, in frames/second. * @property {WebInputMode} inputMode="touch" - The user input mode to use. - * @property {boolean} showKeyboardFocusHighlight=true - true to highlight the entity when it has keyboard focus, - * false to not display the highlight. + * @property {boolean} showKeyboardFocusHighlight=true - true if the entity is highlighted when it has keyboard + * focus, false if it isn't. * @example Create a Web entity displaying at 1920 x 1080 resolution. * var METERS_TO_INCHES = 39.3701; * var entity = Entities.addEntity({ @@ -1380,12 +1386,12 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {Entities.ComponentMode} bloomMode="inherit" - Configures the bloom in the zone. * @property {Entities.Bloom} bloom - The bloom properties of the zone. * - * @property {boolean} flyingAllowed=true - If true then visitors can fly in the zone; otherwise, they cannot. - * Only works for domain entities. - * @property {boolean} ghostingAllowed=true - If true then visitors with avatar collisions turned off will not - * collide with content in the zone; otherwise, visitors will always collide with content in the zone. Only works for domain - * entities. - + * @property {boolean} flyingAllowed=true - true if visitors can fly in the zone; false if they + * cannot. Only works for domain entities. + * @property {boolean} ghostingAllowed=true - true if visitors with avatar collisions turned off will not + * collide with content in the zone; false if visitors will always collide with content in the zone. Only + * works for domain entities. + * * @property {string} filterURL="" - The URL of a JavaScript file that filters changes to properties of entities within the * zone. It is periodically executed for each entity in the zone. It can, for example, be used to not allow changes to * certain properties: @@ -1421,7 +1427,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @typedef {object} Entities.EntityProperties-Image * @property {Vec3} dimensions=0.1,0.1,0.01 - The dimensions of the entity. * @property {string} imageURL="" - The URL of the image to use. - * @property {boolean} emissive=false - true fi the the image should be emissive (unlit), false if it + * @property {boolean} emissive=false - true if the image should be emissive (unlit), false if it * shouldn't. * @property {boolean} keepAspectRatio=true - true if the image should maintain its aspect ratio, * false if it shouldn't. @@ -1432,12 +1438,11 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {Entities.Pulse} pulse - Color and alpha pulse. *

Deprecated: This property is deprecated and will be removed.

* @property {BillboardMode} billboardMode="none" - Whether the entity is billboarded to face the camera. - * @property {boolean} faceCamera - true if billboardMode is "yaw", otherwise - * false. Setting this property to false sets the billboardMode to - * "none". + * @property {boolean} faceCamera - true if billboardMode is "yaw", false + * if it isn't. Setting this property to false sets the billboardMode to "none". *

Deprecated: This property is deprecated and will be removed.

- * @property {boolean} isFacingAvatar - true if billboardMode is "full", otherwise - * false. Setting this property to false sets the billboardMode to + * @property {boolean} isFacingAvatar - true if billboardMode is "full", + * false if it isn't. Setting this property to false sets the billboardMode to * "none". *

Deprecated: This property is deprecated and will be removed.

* @example Create an image entity. @@ -1461,8 +1466,8 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {number} alpha=1 - The opacity of the grid. * @property {Entities.Pulse} pulse - Color and alpha pulse. *

Deprecated: This property is deprecated and will be removed.

- * @property {boolean} followCamera=true - If true, the grid is always visible even as the camera moves to another - * position. + * @property {boolean} followCamera=true - true if the grid is always visible even as the camera moves to another + * position, false if it doesn't follow the camrmea. * @property {number} majorGridEvery=5 - Integer number of minorGridEvery intervals at which to draw a thick grid * line. Minimum value = 1. * @property {number} minorGridEvery=1 - Real number of meters at which to draw thin grid lines. Minimum value = @@ -1721,6 +1726,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_RIGHT_MARGIN, rightMargin); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_TOP_MARGIN, topMargin); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_BOTTOM_MARGIN, bottomMargin); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_UNLIT, unlit); } // Zones only @@ -1895,7 +1901,8 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool * @property {number} verticesCount - The number of vertices in the entity. * @property {number} texturesCount - The number of textures in the entity. * @property {number} texturesSize - The total size of the textures in the entity, in bytes. - * @property {boolean} hasTransparent - Is true if any of the textures has transparency. + * @property {boolean} hasTransparent - true if any of the textures has transparency, false + * if none of them do. * @property {number} drawCalls - The number of draw calls required to render the entity. */ // currently only supported by models @@ -2095,6 +2102,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(rightMargin, float, setRightMargin); COPY_PROPERTY_FROM_QSCRIPTVALUE(topMargin, float, setTopMargin); COPY_PROPERTY_FROM_QSCRIPTVALUE(bottomMargin, float, setBottomMargin); + COPY_PROPERTY_FROM_QSCRIPTVALUE(unlit, bool, setUnlit); // Zone _keyLight.copyFromScriptValue(object, _defaultSettings); @@ -2378,6 +2386,7 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { COPY_PROPERTY_IF_CHANGED(rightMargin); COPY_PROPERTY_IF_CHANGED(topMargin); COPY_PROPERTY_IF_CHANGED(bottomMargin); + COPY_PROPERTY_IF_CHANGED(unlit); // Zone _keyLight.merge(other._keyLight); @@ -2736,6 +2745,7 @@ bool EntityItemProperties::getPropertyInfo(const QString& propertyName, EntityPr ADD_PROPERTY_TO_MAP(PROP_RIGHT_MARGIN, RightMargin, rightMargin, float); ADD_PROPERTY_TO_MAP(PROP_TOP_MARGIN, TopMargin, topMargin, float); ADD_PROPERTY_TO_MAP(PROP_BOTTOM_MARGIN, BottomMargin, bottomMargin, float); + ADD_PROPERTY_TO_MAP(PROP_UNLIT, Unlit, unlit, bool); // Zone { // Keylight @@ -3165,6 +3175,7 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy APPEND_ENTITY_PROPERTY(PROP_RIGHT_MARGIN, properties.getRightMargin()); APPEND_ENTITY_PROPERTY(PROP_TOP_MARGIN, properties.getTopMargin()); APPEND_ENTITY_PROPERTY(PROP_BOTTOM_MARGIN, properties.getBottomMargin()); + APPEND_ENTITY_PROPERTY(PROP_UNLIT, properties.getUnlit()); } if (properties.getType() == EntityTypes::Zone) { @@ -3643,6 +3654,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_RIGHT_MARGIN, float, setRightMargin); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TOP_MARGIN, float, setTopMargin); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BOTTOM_MARGIN, float, setBottomMargin); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_UNLIT, bool, setUnlit); } if (properties.getType() == EntityTypes::Zone) { @@ -4035,6 +4047,7 @@ void EntityItemProperties::markAllChanged() { _rightMarginChanged = true; _topMarginChanged = true; _bottomMarginChanged = true; + _unlitChanged = true; // Zone _keyLight.markAllChanged(); @@ -4624,6 +4637,9 @@ QList EntityItemProperties::listChangedProperties() { if (bottomMarginChanged()) { out += "bottomMargin"; } + if (unlitChanged()) { + out += "unlit"; + } // Zone getKeyLight().listChangedProperties(out); diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 619af97ee5..456ee3cdec 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -314,6 +314,7 @@ public: DEFINE_PROPERTY_REF(PROP_RIGHT_MARGIN, RightMargin, rightMargin, float, TextEntityItem::DEFAULT_MARGIN); DEFINE_PROPERTY_REF(PROP_TOP_MARGIN, TopMargin, topMargin, float, TextEntityItem::DEFAULT_MARGIN); DEFINE_PROPERTY_REF(PROP_BOTTOM_MARGIN, BottomMargin, bottomMargin, float, TextEntityItem::DEFAULT_MARGIN); + DEFINE_PROPERTY_REF(PROP_UNLIT, Unlit, unlit, bool, false); // Zone DEFINE_PROPERTY_GROUP(KeyLight, keyLight, KeyLightPropertyGroup); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index e86cccb997..f98ee913a2 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -241,6 +241,7 @@ enum EntityPropertyList { PROP_RIGHT_MARGIN = PROP_DERIVED_7, PROP_TOP_MARGIN = PROP_DERIVED_8, PROP_BOTTOM_MARGIN = PROP_DERIVED_9, + PROP_UNLIT = PROP_DERIVED_10, // Zone // Keylight diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 0666bb98df..ad2aaf2160 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -59,8 +59,8 @@ private: /**jsdoc * The result of a {@link Entities.findRayIntersection|findRayIntersection} search using a {@link PickRay}. * @typedef {object} Entities.RayToEntityIntersectionResult - * @property {boolean} intersects - true if the {@link PickRay} intersected an entity, otherwise - * false. + * @property {boolean} intersects - true if the {@link PickRay} intersected an entity, false if it + * didn't. * @property {boolean} accurate - Is always true. * @property {Uuid} entityID - The ID if the entity intersected, if any, otherwise null. * @property {number} distance - The distance from the {@link PickRay} origin to the intersection point. @@ -131,8 +131,8 @@ public: * leaveEntity{@link Entities.leaveEntity} * mouseDoublePressOnEntity{@link Entities.mouseDoublePressOnEntity} * mouseMoveOnEntity{@link Entities.mouseMoveOnEntity} - * mouseMoveEventDeprecated: This is a synonym for - * mouseMoveOnEntity. + * mouseMoveEventDeprecated: Use mouseMoveOnEntity + * instead. * mousePressOnEntity{@link Entities.mousePressOnEntity} * mouseReleaseOnEntity{@link Entities.mouseReleaseOnEntity} * @@ -148,8 +148,8 @@ public: * @hifi-assignment-client * * @property {Uuid} keyboardFocusEntity - The {@link Entities.EntityProperties-Web|Web} entity that has keyboard focus. If no - * Web entity has keyboard focus, get returns null; set to null or {@link Uuid(0)|Uuid.NULL} to - * clear keyboard focus. + * Web entity has keyboard focus, returns null; set to null or {@link Uuid(0)|Uuid.NULL} to clear + * keyboard focus. */ /// handles scripting of Entity commands from JS passed to assigned clients class EntityScriptingInterface : public OctreeScriptingInterface, public Dependency { @@ -191,8 +191,8 @@ public: * objects (e.g., the "keyLight" property), use the property and subproperty names in dot notation (e.g., * "keyLight.color"). * @returns {Entities.EntityProperties[]} The specified properties of each entity for each entity that can be found. If - * none of the entities can be found then an empty array. If no properties are specified, then all properties are - * returned. + * none of the entities can be found, then an empty array is returned. If no properties are specified, then all + * properties are returned. * @example Retrieve the names of the nearby entities * var SEARCH_RADIUS = 50; // meters * var entityIDs = Entities.findEntities(MyAvatar.position, SEARCH_RADIUS); @@ -353,9 +353,10 @@ public slots: bool collisionless, bool grabbable, const glm::vec3& position, const glm::vec3& gravity); /**jsdoc - * Creates a clone of an entity. The clone has a modified name property, other properties set per the original - * entity's clone-related {@link Entities.EntityProperties|properties} (e.g., cloneLifetime), and - * clone-related properties set to defaults. + * Creates a clone of an entity. The clone has the same properties as the original except that: it has a modified + * name property, clone-related properties are set per the original entity's clone-related + * {@link Entities.EntityProperties|properties} (e.g., cloneLifetime), and its clone-related properties are + * set to their defaults. *

Domain entities must have their cloneable property value be true in order to be cloned. A * domain entity can be cloned by a client that doesn't have rez permissions in the domain.

*

Avatar entities must have their cloneable and cloneAvatarEntity property values be @@ -507,7 +508,7 @@ public slots: Q_INVOKABLE QObject* getEntityObject(const QUuid& id); /**jsdoc - * Checks whether an entities's assets have been loaded. For example, for an Model entity the result indicates + * Checks whether an entity's assets have been loaded. For example, for an Model entity the result indicates * whether its textures have been loaded. * @function Entities.isLoaded * @param {Uuid} id - The ID of the entity to check. @@ -747,7 +748,8 @@ public slots: * @param {string} entityName - The name of the entity to search for. * @param {Vec3} center - The point about which to search. * @param {number} radius - The radius within which to search. - * @param {boolean} [caseSensitive=false] - If true then the search is case-sensitive. + * @param {boolean} [caseSensitive=false] - true if the search is case-sensitive, false if it is + * case-insensitive. * @returns {Uuid[]} An array of entity IDs that have the specified name and intersect the search sphere. The array is * empty if no entities could be found. * @example Report the number of entities with the name, "Light-Target". @@ -767,12 +769,14 @@ public slots: * @param {boolean} [precisionPicking=false] - true to pick against precise meshes, false to pick * against coarse meshes. If true and the intersected entity is a Model entity, the result's * extraInfo property includes more information than it otherwise would. - * @param {Uuid[]} [entitiesToInclude=[]] - If not empty then the search is restricted to these entities. + * @param {Uuid[]} [entitiesToInclude=[]] - If not empty, then the search is restricted to these entities. * @param {Uuid[]} [entitiesToDiscard=[]] - Entities to ignore during the search. - * @param {boolean} [visibleOnly=false] - If true then only entities that are - * {@link Entities.EntityProperties|visible} are searched. - * @param {boolean} [collideableOnly=false] - If true then only entities that are not - * {@link Entities.EntityProperties|collisionless} are searched. + * @param {boolean} [visibleOnly=false] - true if only entities that are + * {@link Entities.EntityProperties|visible} are searched for, false if their visibility + * doesn't matter. + * @param {boolean} [collideableOnly=false] - true if only entities that are not + * {@link Entities.EntityProperties|collisionless} are searched, false if their + * collideability doesn't matter. * @returns {Entities.RayToEntityIntersectionResult} The result of the search for the first intersected entity. * @example Find the entity directly in front of your avatar. * var pickRay = { @@ -856,7 +860,7 @@ public slots: /**jsdoc * Sets whether or not ray picks intersect the bounding box of {@link Entities.EntityProperties-Light|Light} entities. By - * default, Light entities are not intersected. The setting lasts for the Interface session. Ray picks are done using + * default, Light entities are not intersected. The setting lasts for the Interface session. Ray picks are performed using * {@link Entities.findRayIntersection|findRayIntersection}, or the {@link Picks} API. * @function Entities.setLightsArePickable * @param {boolean} value - true to make ray picks intersect the bounding box of @@ -867,7 +871,7 @@ public slots: /**jsdoc * Gets whether or not ray picks intersect the bounding box of {@link Entities.EntityProperties-Light|Light} entities. Ray - * picks are done using {@link Entities.findRayIntersection|findRayIntersection}, or the {@link Picks} API. + * picks are performed using {@link Entities.findRayIntersection|findRayIntersection}, or the {@link Picks} API. * @function Entities.getLightsArePickable * @returns {boolean} true if ray picks intersect the bounding box of * {@link Entities.EntityProperties-Light|Light} entities, otherwise false. @@ -877,7 +881,7 @@ public slots: /**jsdoc * Sets whether or not ray picks intersect the bounding box of {@link Entities.EntityProperties-Zone|Zone} entities. By - * default, Zone entities are not intersected. The setting lasts for the Interface session. Ray picks are done using + * default, Zone entities are not intersected. The setting lasts for the Interface session. Ray picks are performed using * {@link Entities.findRayIntersection|findRayIntersection}, or the {@link Picks} API. * @function Entities.setZonesArePickable * @param {boolean} value - true to make ray picks intersect the bounding box of @@ -888,7 +892,7 @@ public slots: /**jsdoc * Gets whether or not ray picks intersect the bounding box of {@link Entities.EntityProperties-Zone|Zone} entities. Ray - * picks are done using {@link Entities.findRayIntersection|findRayIntersection}, or the {@link Picks} API. + * picks are performed using {@link Entities.findRayIntersection|findRayIntersection}, or the {@link Picks} API. * @function Entities.getZonesArePickable * @returns {boolean} true if ray picks intersect the bounding box of * {@link Entities.EntityProperties-Zone|Zone} entities, otherwise false. @@ -1068,7 +1072,7 @@ public slots: * the dimensions of each voxel. * @function Entities.worldCoordsToVoxelCoords * @param {Uuid} entityID - The ID of the {@link Entities.EntityProperties-PolyVox|PolyVox} entity. - * @param {Vec3} worldCoords - The world coordinates. May be outside the entity's bounding box. + * @param {Vec3} worldCoords - The world coordinates. The value may be outside the entity's bounding box. * @returns {Vec3} The voxel coordinates of the worldCoords if the entityID is a * {@link Entities.EntityProperties-PolyVox|PolyVox} entity, otherwise {@link Vec3(0)|Vec3.ZERO}. The value may be * fractional and outside the entity's bounding box. @@ -1083,7 +1087,7 @@ public slots: * Vec3.ONE being the dimensions of each voxel. * @function Entities.voxelCoordsToLocalCoords * @param {Uuid} entityID - The ID of the {@link Entities.EntityProperties-PolyVox|PolyVox} entity. - * @param {Vec3} voxelCoords - The voxel coordinates. May be fractional and outside the entity's bounding box. + * @param {Vec3} voxelCoords - The voxel coordinates. The value may be fractional and outside the entity's bounding box. * @returns {Vec3} The local coordinates of the voxelCoords if the entityID is a * {@link Entities.EntityProperties-PolyVox|PolyVox} entity, otherwise {@link Vec3(0)|Vec3.ZERO}. * @example Get the world dimensions of a voxel in a PolyVox entity. @@ -1107,7 +1111,7 @@ public slots: * Vec3.ONE being the dimensions of each voxel. * @function Entities.localCoordsToVoxelCoords * @param {Uuid} entityID - The ID of the {@link Entities.EntityProperties-PolyVox|PolyVox} entity. - * @param {Vec3} localCoords - The local coordinates. May be outside the entity's bounding box. + * @param {Vec3} localCoords - The local coordinates. The value may be outside the entity's bounding box. * @returns {Vec3} The voxel coordinates of the worldCoords if the entityID is a * {@link Entities.EntityProperties-PolyVox|PolyVox} entity, otherwise {@link Vec3(0)|Vec3.ZERO}. The value may be * fractional and outside the entity's bounding box. @@ -2105,7 +2109,7 @@ public slots: * @function Entities.getPropertyInfo * @param {string} propertyName - The name of the property to get the information for. * @returns {Entities.EntityPropertyInfo} The information about the property if it can be found, otherwise an empty object. - * @example Report property info. for some properties. + * @example Report property information for some properties. * print("alpha: " + JSON.stringify(Entities.getPropertyInfo("alpha"))); * print("script: " + JSON.stringify(Entities.getPropertyInfo("script"))); */ @@ -2209,7 +2213,7 @@ signals: /**jsdoc * Triggered when your ability to make changes to the asset server's assets changes. * @function Entities.canWriteAssetsChanged - * @param {boolean} canWriteAssets - true if the script can change the ? property of an entity, + * @param {boolean} canWriteAssets - true if the script can change the asset server's assets, * false if it can't. * @returns {Signal} */ diff --git a/libraries/entities/src/GrabPropertyGroup.h b/libraries/entities/src/GrabPropertyGroup.h index 75804378aa..9fa58273be 100644 --- a/libraries/entities/src/GrabPropertyGroup.h +++ b/libraries/entities/src/GrabPropertyGroup.h @@ -44,19 +44,20 @@ static const glm::vec3 INITIAL_EQUIPPABLE_INDICATOR_OFFSET { glm::vec3(0.0f) }; * Grabbing behavior is defined by the following properties: * * @typedef {object} Entities.Grab - * @property {boolean} grabbable=true - If true then the entity can be grabbed. - * @property {boolean} grabKinematic=true - If true then the entity will be updated in a kinematic manner when - * grabbed; if false it will be grabbed using a tractor action. A kinematic grab will make the item appear + * @property {boolean} grabbable=true - true if the entity can be grabbed, false if it can't be. + * @property {boolean} grabKinematic=true - true if the entity will be updated in a kinematic manner when + * grabbed; false if it will be grabbed using a tractor action. A kinematic grab will make the item appear * more tightly held but will cause it to behave poorly when interacting with dynamic entities. - * @property {boolean} grabFollowsController=true - If true then the entity will follow the motions of the hand - * controller even if the avatar's hand can't get to the implied position. This should be set true for tools, - * pens, etc. and false for things meant to decorate the hand. - * @property {boolean} triggerable=false - If true then the entity will receive calls to trigger - * {@link Controller|Controller entity methods}. - * @property {boolean} grabDelegateToParent=true - If true and the entity is grabbed, the grab will be transferred - * to its parent entity if there is one; if false, a child entity can be grabbed and moved relative to its - * parent. - * @property {boolean} equippable=true - If true then the entity can be equipped. + * @property {boolean} grabFollowsController=true - true if the entity will follow the motions of the hand + * controller even if the avatar's hand can't get to the implied position, false if it will follow the motions + * of the avatar's hand. This should be set true for tools, pens, etc. and false for things meant +* to decorate the hand. + * @property {boolean} triggerable=false - true if the entity will receive calls to trigger + * {@link Controller|Controller entity methods}, false if it won't. + * @property {boolean} grabDelegateToParent=true - true if when the entity is grabbed, the grab will be + * transferred to its parent entity if there is one; false if the grab won't be transferred, so a child entity + * can be grabbed and moved relative to its parent. + * @property {boolean} equippable=true - true if the entity can be equipped, false if it cannot. * @property {Vec3} equippableLeftPosition=0,0,0 - Positional offset from the left hand, when equipped. * @property {Quat} equippableLeftRotation=0,0,0,1 - Rotational offset from the left hand, when equipped. * @property {Vec3} equippableRightPosition=0,0,0 - Positional offset from the right hand, when equipped. diff --git a/libraries/entities/src/HazePropertyGroup.h b/libraries/entities/src/HazePropertyGroup.h index 116bfd9687..59a36b6f7f 100644 --- a/libraries/entities/src/HazePropertyGroup.h +++ b/libraries/entities/src/HazePropertyGroup.h @@ -49,14 +49,16 @@ static const float INITIAL_KEY_LIGHT_ALTITUDE{ 200.0f }; * @property {number} hazeRange=1000 - The horizontal distance at which visibility is reduced to 95%; i.e., 95% of each pixel's * color is haze. * @property {Color} hazeColor=128,154,179 - The color of the haze when looking away from the key light. - * @property {boolean} hazeEnableGlare=false - If true then the haze is colored with glare from the key light; - * hazeGlareColor and hazeGlareAngle are used. + * @property {boolean} hazeEnableGlare=false - true if the haze is colored with glare from the key light, + * false if it isn't. If true, then hazeGlareColor and hazeGlareAngle + * are used. * @property {Color} hazeGlareColor=255,299,179 - The color of the haze when looking towards the key light. * @property {number} hazeGlareAngle=20 - The angle in degrees across the circle around the key light that the glare color and * haze color are blended 50/50. * - * @property {boolean} hazeAltitudeEffect=false - If true then haze decreases with altitude as defined by the - * entity's local coordinate system; hazeBaseRef and hazeCeiling are used. + * @property {boolean} hazeAltitudeEffect=false - true if haze decreases with altitude as defined by the + * entity's local coordinate system, false if it doesn't. If true, then hazeBaseRef + * and hazeCeiling are used. * @property {number} hazeBaseRef=0 - The y-axis value in the entity's local coordinate system at which the haze density starts * reducing with altitude. * @property {number} hazeCeiling=200 - The y-axis value in the entity's local coordinate system at which the haze density has @@ -65,8 +67,8 @@ static const float INITIAL_KEY_LIGHT_ALTITUDE{ 200.0f }; * @property {number} hazeBackgroundBlend=0 - The proportion of the skybox image to show through the haze: 0.0 * displays no skybox image; 1.0 displays no haze. * - * @property {boolean} hazeAttenuateKeyLight=false - If true then the haze attenuates the key light; - * hazeKeyLightRange and hazeKeyLightAltitude are used. + * @property {boolean} hazeAttenuateKeyLight=false - true if the haze attenuates the key light, false + * if it doesn't. If true, then hazeKeyLightRange and hazeKeyLightAltitude are used. * @property {number} hazeKeyLightRange=1000 - The distance at which the haze attenuates the key light by 95%. * @property {number} hazeKeyLightAltitude=200 - The altitude at which the haze starts attenuating the key light (i.e., the * altitude at which the distance starts being calculated). diff --git a/libraries/entities/src/KeyLightPropertyGroup.h b/libraries/entities/src/KeyLightPropertyGroup.h index 31e0cba1c6..d46f5ce9b5 100644 --- a/libraries/entities/src/KeyLightPropertyGroup.h +++ b/libraries/entities/src/KeyLightPropertyGroup.h @@ -33,8 +33,9 @@ class ReadBitstreamToTreeParams; * @property {Color} color=255,255,255 - The color of the light. * @property {number} intensity=1 - The intensity of the light. * @property {Vec3} direction=0,-1,0 - The direction the light is shining. - * @property {boolean} castShadows=false - If true then shadows are cast. Shadows are cast by avatars, plus - * {@link Entities.EntityProperties-Model|Model} and {@link Entities.EntityProperties-Shape|Shape} entities that have their + * @property {boolean} castShadows=false - true if shadows are cast, false if they aren't. Shadows + * are cast by avatars, plus {@link Entities.EntityProperties-Model|Model} and + * {@link Entities.EntityProperties-Shape|Shape} entities that have their * {@link Entities.EntityProperties|canCastShadow} property set to true. */ class KeyLightPropertyGroup : public PropertyGroup { diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index 5dff645c89..08200084f4 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -64,6 +64,7 @@ EntityItemProperties TextEntityItem::getProperties(const EntityPropertyFlags& de COPY_ENTITY_PROPERTY_TO_PROPERTIES(rightMargin, getRightMargin); COPY_ENTITY_PROPERTY_TO_PROPERTIES(topMargin, getTopMargin); COPY_ENTITY_PROPERTY_TO_PROPERTIES(bottomMargin, getBottomMargin); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(unlit, getUnlit); return properties; } @@ -87,6 +88,7 @@ bool TextEntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(rightMargin, setRightMargin); SET_ENTITY_PROPERTY_FROM_PROPERTIES(topMargin, setTopMargin); SET_ENTITY_PROPERTY_FROM_PROPERTIES(bottomMargin, setBottomMargin); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(unlit, setUnlit); if (somethingChanged) { bool wantDebug = false; @@ -129,7 +131,8 @@ int TextEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, READ_ENTITY_PROPERTY(PROP_RIGHT_MARGIN, float, setRightMargin); READ_ENTITY_PROPERTY(PROP_TOP_MARGIN, float, setTopMargin); READ_ENTITY_PROPERTY(PROP_BOTTOM_MARGIN, float, setBottomMargin); - + READ_ENTITY_PROPERTY(PROP_UNLIT, bool, setUnlit); + return bytesRead; } @@ -149,6 +152,7 @@ EntityPropertyFlags TextEntityItem::getEntityProperties(EncodeBitstreamParams& p requestedProperties += PROP_RIGHT_MARGIN; requestedProperties += PROP_TOP_MARGIN; requestedProperties += PROP_BOTTOM_MARGIN; + requestedProperties += PROP_UNLIT; return requestedProperties; } @@ -179,6 +183,7 @@ void TextEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits APPEND_ENTITY_PROPERTY(PROP_RIGHT_MARGIN, getRightMargin()); APPEND_ENTITY_PROPERTY(PROP_TOP_MARGIN, getTopMargin()); APPEND_ENTITY_PROPERTY(PROP_BOTTOM_MARGIN, getBottomMargin()); + APPEND_ENTITY_PROPERTY(PROP_UNLIT, getUnlit()); } glm::vec3 TextEntityItem::getRaycastDimensions() const { @@ -382,6 +387,18 @@ float TextEntityItem::getBottomMargin() const { }); } +void TextEntityItem::setUnlit(bool value) { + withWriteLock([&] { + _unlit = value; + }); +} + +bool TextEntityItem::getUnlit() const { + return resultWithReadLock([&] { + return _unlit; + }); +} + PulsePropertyGroup TextEntityItem::getPulseProperties() const { return resultWithReadLock([&] { return _pulseProperties; diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index 1ead9d3e15..a962482cde 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -97,6 +97,9 @@ public: float getBottomMargin() const; void setBottomMargin(float value); + bool getUnlit() const; + void setUnlit(bool value); + PulsePropertyGroup getPulseProperties() const; private: @@ -113,6 +116,7 @@ private: float _rightMargin; float _topMargin; float _bottomMargin; + bool _unlit; }; #endif // hifi_TextEntityItem_h diff --git a/libraries/gpu/src/gpu/DrawTextureGammaLinearToSRGB.slf b/libraries/gpu/src/gpu/DrawTextureLinearToSRGB.slf similarity index 94% rename from libraries/gpu/src/gpu/DrawTextureGammaLinearToSRGB.slf rename to libraries/gpu/src/gpu/DrawTextureLinearToSRGB.slf index 3ca3a92f01..9d78e7286b 100644 --- a/libraries/gpu/src/gpu/DrawTextureGammaLinearToSRGB.slf +++ b/libraries/gpu/src/gpu/DrawTextureLinearToSRGB.slf @@ -2,7 +2,7 @@ <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // -// DrawTextureGammaLinearToSRGB.frag +// DrawTextureLinearToSRGB.frag // // Draw texture 0 fetched at texcoord.xy, and apply linear to sRGB color space conversion // diff --git a/libraries/gpu/src/gpu/DrawTextureGammaLinearToSRGB.slp b/libraries/gpu/src/gpu/DrawTextureLinearToSRGB.slp similarity index 100% rename from libraries/gpu/src/gpu/DrawTextureGammaLinearToSRGB.slp rename to libraries/gpu/src/gpu/DrawTextureLinearToSRGB.slp diff --git a/libraries/gpu/src/gpu/DrawTextureMirroredX.slf b/libraries/gpu/src/gpu/DrawTextureMirroredX.slf index abb52cbe7f..f959d8480b 100644 --- a/libraries/gpu/src/gpu/DrawTextureMirroredX.slf +++ b/libraries/gpu/src/gpu/DrawTextureMirroredX.slf @@ -13,6 +13,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Color.slh@> LAYOUT(binding=0) uniform sampler2D colorMap; @@ -20,5 +21,5 @@ layout(location=0) in vec2 varTexCoord0; layout(location=0) out vec4 outFragColor; void main(void) { - outFragColor = texture(colorMap, vec2(1.0 - varTexCoord0.x, varTexCoord0.y)); + outFragColor = vec4(texture(colorMap, vec2(1.0 - varTexCoord0.x, varTexCoord0.y)).xyz, 1.0); } diff --git a/libraries/gpu/src/gpu/DrawTextureMirroredX.slp b/libraries/gpu/src/gpu/DrawTextureMirroredX.slp index db9a4a4fac..e18f38ec1b 100644 --- a/libraries/gpu/src/gpu/DrawTextureMirroredX.slp +++ b/libraries/gpu/src/gpu/DrawTextureMirroredX.slp @@ -1 +1 @@ -VERTEX DrawUnitQuadTexcoord \ No newline at end of file +VERTEX DrawTransformUnitQuad \ No newline at end of file diff --git a/libraries/gpu/src/gpu/DrawTextureOpaque.slf b/libraries/gpu/src/gpu/DrawTextureOpaque.slf index e23529e851..458eff75ed 100755 --- a/libraries/gpu/src/gpu/DrawTextureOpaque.slf +++ b/libraries/gpu/src/gpu/DrawTextureOpaque.slf @@ -14,8 +14,6 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include gpu/ShaderConstants.h@> - LAYOUT(binding=0) uniform sampler2D colorMap; layout(location=0) in vec2 varTexCoord0; diff --git a/libraries/gpu/src/gpu/DrawTextureGammaSRGBToLinear.slf b/libraries/gpu/src/gpu/DrawTextureSRGBToLinear.slf similarity index 94% rename from libraries/gpu/src/gpu/DrawTextureGammaSRGBToLinear.slf rename to libraries/gpu/src/gpu/DrawTextureSRGBToLinear.slf index 870967ec3a..772d45131a 100644 --- a/libraries/gpu/src/gpu/DrawTextureGammaSRGBToLinear.slf +++ b/libraries/gpu/src/gpu/DrawTextureSRGBToLinear.slf @@ -2,7 +2,7 @@ <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // -// DrawTextureGammaSRGBToLinear.frag +// DrawTextureSRGBToLinear.frag // // Draw texture 0 fetched at texcoord.xy, and apply sRGB to Linear color space conversion // diff --git a/libraries/gpu/src/gpu/DrawTextureGammaSRGBToLinear.slp b/libraries/gpu/src/gpu/DrawTextureSRGBToLinear.slp similarity index 100% rename from libraries/gpu/src/gpu/DrawTextureGammaSRGBToLinear.slp rename to libraries/gpu/src/gpu/DrawTextureSRGBToLinear.slp diff --git a/libraries/graphics/src/graphics/Haze.cpp b/libraries/graphics/src/graphics/Haze.cpp index d9bee7507f..9e3cc15c57 100644 --- a/libraries/graphics/src/graphics/Haze.cpp +++ b/libraries/graphics/src/graphics/Haze.cpp @@ -98,7 +98,7 @@ void Haze::setHazeGlareColor(const glm::vec3 hazeGlareColor) { void Haze::setHazeActive(const bool isHazeActive) { auto& params = _hazeParametersBuffer.get(); - if (((params.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE )&& !isHazeActive) { + if (((params.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) && !isHazeActive) { _hazeParametersBuffer.edit().hazeMode &= ~HAZE_MODE_IS_ACTIVE; } else if (((params.hazeMode & HAZE_MODE_IS_ACTIVE) != HAZE_MODE_IS_ACTIVE) && isHazeActive) { _hazeParametersBuffer.edit().hazeMode |= HAZE_MODE_IS_ACTIVE; diff --git a/libraries/render-utils/src/Haze.slh b/libraries/graphics/src/graphics/Haze.slh similarity index 97% rename from libraries/render-utils/src/Haze.slh rename to libraries/graphics/src/graphics/Haze.slh index e2285febe4..a2d8bb0523 100644 --- a/libraries/render-utils/src/Haze.slh +++ b/libraries/graphics/src/graphics/Haze.slh @@ -10,7 +10,7 @@ <@if not HAZE_SLH@> <@def HAZE_SLH@> -<@include render-utils/ShaderConstants.h@> +<@include graphics/ShaderConstants.h@> const int HAZE_MODE_IS_ACTIVE = 1 << 0; const int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1; @@ -38,8 +38,7 @@ struct HazeParams { float hazeKeyLightAltitudeFactor; }; -// See ShapePipeline::Slot::BUFFER in ShapePipeline.h -LAYOUT_STD140(binding=RENDER_UTILS_BUFFER_HAZE_PARAMS) uniform hazeBuffer { +LAYOUT_STD140(binding=GRAPHICS_BUFFER_HAZE_PARAMS) uniform hazeBuffer { HazeParams hazeParams; }; diff --git a/libraries/graphics/src/graphics/Light.cpp b/libraries/graphics/src/graphics/Light.cpp index 8a7281880e..a5d03beda1 100755 --- a/libraries/graphics/src/graphics/Light.cpp +++ b/libraries/graphics/src/graphics/Light.cpp @@ -89,6 +89,14 @@ float Light::getShadowsBiasScale() const { return _shadowsBiasScale; } +void Light::setBiasInput(float bias) { + _biasInput = bias; +} + +float Light::getBiasInput() const { + return _biasInput; +} + void Light::setColor(const Color& color) { _lightSchemaBuffer.edit().irradiance.color = color; updateLightRadius(); diff --git a/libraries/graphics/src/graphics/Light.h b/libraries/graphics/src/graphics/Light.h index 824a9138c0..9b431b3e26 100755 --- a/libraries/graphics/src/graphics/Light.h +++ b/libraries/graphics/src/graphics/Light.h @@ -112,6 +112,9 @@ public: void setShadowsBiasScale(const float scale); float getShadowsBiasScale() const; + void setBiasInput(float bias); + float getBiasInput() const; + void setOrientation(const Quat& orientation); const glm::quat& getOrientation() const { return _transform.getRotation(); } @@ -200,6 +203,7 @@ protected: float _shadowsMaxDistance{ 40.0f }; float _shadowsBiasScale{ 1.0f }; + float _biasInput{ 0.5f }; // 0.23f will roughly give the default constant and slope values bool _castShadows{ false }; void updateLightRadius(); diff --git a/libraries/graphics/src/graphics/ShaderConstants.h b/libraries/graphics/src/graphics/ShaderConstants.h index 0aff0a7077..3a614d26cd 100644 --- a/libraries/graphics/src/graphics/ShaderConstants.h +++ b/libraries/graphics/src/graphics/ShaderConstants.h @@ -32,6 +32,8 @@ #define GRAPHICS_TEXTURE_SKYBOX 11 #define GRAPHICS_BUFFER_SKYBOX_PARAMS 5 +#define GRAPHICS_BUFFER_HAZE_PARAMS 7 + // (); +static std::map _pipelines; + +void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Skybox& skybox, bool forward) { + if (_pipelines.empty()) { + static const std::vector> keys = { + std::make_tuple(false, shader::graphics::program::skybox), + std::make_tuple(true, shader::graphics::program::skybox_forward) + }; + for (auto& key : keys) { + auto state = std::make_shared(); // Must match PrepareStencil::STENCIL_BACKGROUND const int8_t STENCIL_BACKGROUND = 0; - skyState->setStencilTest(true, 0xFF, gpu::State::StencilTest(STENCIL_BACKGROUND, 0xFF, gpu::EQUAL, + state->setStencilTest(true, 0xFF, gpu::State::StencilTest(STENCIL_BACKGROUND, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); - thePipeline = gpu::Pipeline::create(skyShader, skyState); + _pipelines[std::get<0>(key)] = gpu::Pipeline::create(gpu::Shader::createProgram(std::get<1>(key)), state); } - }); - + } // Render glm::mat4 projMat; @@ -111,7 +111,7 @@ void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Sky batch.setViewTransform(viewTransform); batch.setModelTransform(Transform()); // only for Mac - batch.setPipeline(thePipeline); + batch.setPipeline(_pipelines[forward]); skybox.prepare(batch); batch.draw(gpu::TRIANGLE_STRIP, 4); diff --git a/libraries/graphics/src/graphics/Skybox.h b/libraries/graphics/src/graphics/Skybox.h index 50189f4c51..5668604c8b 100755 --- a/libraries/graphics/src/graphics/Skybox.h +++ b/libraries/graphics/src/graphics/Skybox.h @@ -44,9 +44,9 @@ public: virtual void clear(); void prepare(gpu::Batch& batch) const; - virtual void render(gpu::Batch& batch, const ViewFrustum& frustum) const; + virtual void render(gpu::Batch& batch, const ViewFrustum& frustum, bool forward) const; - static void render(gpu::Batch& batch, const ViewFrustum& frustum, const Skybox& skybox); + static void render(gpu::Batch& batch, const ViewFrustum& frustum, const Skybox& skybox, bool forward); const UniformBufferView& getSchemaBuffer() const { return _schemaBuffer; } diff --git a/libraries/graphics/src/graphics/skybox.slf b/libraries/graphics/src/graphics/skybox.slf index 801fc33c28..4ae53a657f 100755 --- a/libraries/graphics/src/graphics/skybox.slf +++ b/libraries/graphics/src/graphics/skybox.slf @@ -1,8 +1,7 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> +// <$_SCRIBE_FILENAME$> // Generated on <$_SCRIBE_DATE$> -// skybox.frag -// fragment shader // // Created by Sam Gateau on 5/5/2015. // Copyright 2015 High Fidelity, Inc. @@ -12,6 +11,16 @@ // <@include graphics/ShaderConstants.h@> +<@if HIFI_USE_FORWARD@> + <@include gpu/Transform.slh@> + <$declareStandardCameraTransform()$> + + <@include graphics/Light.slh@> + <$declareLightBuffer()$> + + <@include graphics/Haze.slh@> +<@endif@> + LAYOUT(binding=GRAPHICS_TEXTURE_SKYBOX) uniform samplerCube cubeMap; struct Skybox { @@ -32,8 +41,28 @@ void main(void) { // mix(skyboxColor, skyboxTexel, skybox.color.a) // and the blend factor should be user controlled - vec3 skyboxTexel = texture(cubeMap, normalize(_normal)).rgb; + vec3 normal = normalize(_normal); + vec3 skyboxTexel = texture(cubeMap, normal).rgb; vec3 skyboxColor = skybox.color.rgb; _fragColor = vec4(mix(vec3(1.0), skyboxTexel, float(skybox.color.a > 0.0)) * mix(vec3(1.0), skyboxColor, float(skybox.color.a < 1.0)), 1.0); + +<@if HIFI_USE_FORWARD@> + // FIXME: either move this elsewhere or give it access to isHazeEnabled() (which is in render-utils/LightingModel.slh) + if (/*(isHazeEnabled() > 0.0) && */(hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) { + TransformCamera cam = getTransformCamera(); + vec4 eyePositionWS = cam._viewInverse[3]; + // We choose an arbitrary large number > BLEND_DISTANCE in Haze.slh + const float SKYBOX_DISTANCE = 32000.0; + vec4 fragPositionWS = eyePositionWS + SKYBOX_DISTANCE * vec4(normal, 0.0); + vec4 fragPositionES = cam._view * fragPositionWS; + + Light light = getKeyLight(); + vec3 lightDirectionWS = getLightDirection(light); + + vec4 hazeColor = computeHazeColor(fragPositionES.xyz, fragPositionWS.xyz, eyePositionWS.xyz, lightDirectionWS); + _fragColor.rgb = mix(_fragColor.rgb, hazeColor.rgb, hazeColor.a); + } +<@endif@> + } diff --git a/libraries/graphics/src/graphics/skybox.slp b/libraries/graphics/src/graphics/skybox.slp index e69de29bb2..e9908ffd1b 100644 --- a/libraries/graphics/src/graphics/skybox.slp +++ b/libraries/graphics/src/graphics/skybox.slp @@ -0,0 +1 @@ +DEFINES forward:f \ No newline at end of file diff --git a/libraries/graphics/src/graphics/skybox.slv b/libraries/graphics/src/graphics/skybox.slv index 4b14872df2..a6e6930d22 100755 --- a/libraries/graphics/src/graphics/skybox.slv +++ b/libraries/graphics/src/graphics/skybox.slv @@ -1,8 +1,7 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> +// <$_SCRIBE_FILENAME$> // Generated on <$_SCRIBE_DATE$> -// skybox.vert -// vertex shader // // Created by Sam Gateau on 5/5/2015. // Copyright 2015 High Fidelity, Inc. @@ -12,7 +11,6 @@ // <@include gpu/Transform.slh@> - <$declareStandardTransform()$> layout(location=0) out vec3 _normal; diff --git a/libraries/model-baker/src/model-baker/ParseMaterialMappingTask.cpp b/libraries/model-baker/src/model-baker/ParseMaterialMappingTask.cpp index 17b62d0915..c4c4f7f74b 100644 --- a/libraries/model-baker/src/model-baker/ParseMaterialMappingTask.cpp +++ b/libraries/model-baker/src/model-baker/ParseMaterialMappingTask.cpp @@ -61,7 +61,7 @@ void processMaterialMapping(MaterialMapping& materialMapping, const QJsonObject& } else if (mappingJSON.isString()) { auto mappingValue = mappingJSON.toString(); materialMapping.push_back(std::pair(mapping.toStdString(), - MaterialCache::instance().getMaterial(url.resolved(mappingValue)))); + DependencyManager::get()->getMaterial(url.resolved(mappingValue)))); } } } diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index e2e9d33eb6..6cb1582dca 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -86,12 +86,14 @@ AccountManager::AccountManager(UserAgentGetter userAgentGetter) : qRegisterMetaType("QHttpMultiPart*"); qRegisterMetaType(); + connect(this, &AccountManager::loginComplete, this, &AccountManager::uploadPublicKey); } const QString DOUBLE_SLASH_SUBSTITUTE = "slashslash"; const QString ACCOUNT_MANAGER_REQUESTED_SCOPE = "owner"; void AccountManager::logout() { + // a logout means we want to delete the DataServerAccountInfo we currently have for this URL, in-memory and in file _accountInfo = DataServerAccountInfo(); @@ -837,18 +839,30 @@ void AccountManager::generateNewKeypair(bool isUserKeypair, const QUuid& domainI connect(keypairGenerator, &RSAKeypairGenerator::errorGeneratingKeypair, this, &AccountManager::handleKeypairGenerationError); - qCDebug(networking) << "Starting worker thread to generate 2048-bit RSA keypair."; + static constexpr int RSA_THREAD_PRIORITY = 1; + qCDebug(networking) << "Starting worker thread to generate 2048-bit RSA keypair, priority" + << RSA_THREAD_PRIORITY << "- QThreadPool::maxThreadCount =" << QThreadPool::globalInstance()->maxThreadCount(); // Start on Qt's global thread pool. - QThreadPool::globalInstance()->start(keypairGenerator); + QThreadPool::globalInstance()->start(keypairGenerator, RSA_THREAD_PRIORITY); } } void AccountManager::processGeneratedKeypair(QByteArray publicKey, QByteArray privateKey) { - qCDebug(networking) << "Generated 2048-bit RSA keypair. Uploading public key now."; + qCDebug(networking) << "Generated 2048-bit RSA keypair."; // hold the private key to later set our metaverse API account info if upload succeeds + _pendingPublicKey = publicKey; _pendingPrivateKey = privateKey; + uploadPublicKey(); +} + +void AccountManager::uploadPublicKey() { + if (_pendingPrivateKey.isEmpty()) { + return; + } + + qCDebug(networking) << "Attempting upload of public key"; // upload the public key so data-web has an up-to-date key const QString USER_PUBLIC_KEY_UPDATE_PATH = "api/v1/user/public_key"; @@ -870,7 +884,7 @@ void AccountManager::processGeneratedKeypair(QByteArray publicKey, QByteArray pr publicKeyPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"public_key\"; filename=\"public_key\"")); - publicKeyPart.setBody(publicKey); + publicKeyPart.setBody(_pendingPublicKey); requestMultiPart->append(publicKeyPart); // Currently broken? We don't have the temporary domain key. @@ -899,6 +913,7 @@ void AccountManager::publicKeyUploadSucceeded(QNetworkReply* reply) { // public key upload complete - store the matching private key and persist the account to settings _accountInfo.setPrivateKey(_pendingPrivateKey); + _pendingPublicKey.clear(); _pendingPrivateKey.clear(); persistAccountToFile(); @@ -914,9 +929,6 @@ void AccountManager::publicKeyUploadFailed(QNetworkReply* reply) { // we aren't waiting for a response any longer _isWaitingForKeypairResponse = false; - - // clear our pending private key - _pendingPrivateKey.clear(); } void AccountManager::handleKeypairGenerationError() { @@ -959,4 +971,8 @@ void AccountManager::saveLoginStatus(bool isLoggedIn) { QMetaObject::invokeMethod(qApp, "quit", Qt::QueuedConnection); } } -} \ No newline at end of file +} + +bool AccountManager::hasKeyPair() const { + return _accountInfo.hasPrivateKey(); +} diff --git a/libraries/networking/src/AccountManager.h b/libraries/networking/src/AccountManager.h index c2187f79cb..a88a5cc4e7 100644 --- a/libraries/networking/src/AccountManager.h +++ b/libraries/networking/src/AccountManager.h @@ -81,6 +81,7 @@ public: bool needsToRefreshToken(); Q_INVOKABLE bool checkAndSignalForAccessToken(); void setAccessTokenForCurrentAuthURL(const QString& accessToken); + bool hasKeyPair() const; void requestProfile(); @@ -139,6 +140,7 @@ signals: private slots: void handleKeypairGenerationError(); void processGeneratedKeypair(QByteArray publicKey, QByteArray privateKey); + void uploadPublicKey(); void publicKeyUploadSucceeded(QNetworkReply* reply); void publicKeyUploadFailed(QNetworkReply* reply); void generateNewKeypair(bool isUserKeypair = true, const QUuid& domainID = QUuid()); @@ -162,6 +164,7 @@ private: bool _isWaitingForKeypairResponse { false }; QByteArray _pendingPrivateKey; + QByteArray _pendingPublicKey; QUuid _sessionID { QUuid::createUuid() }; diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index ac0f9e0b07..7d2f085d6f 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -584,7 +584,7 @@ SharedNodePointer LimitedNodeList::nodeWithLocalID(Node::LocalID localID) const return idIter == _localIDMap.cend() ? nullptr : idIter->second; } -void LimitedNodeList::eraseAllNodes() { +void LimitedNodeList::eraseAllNodes(QString reason) { std::vector killedNodes; { @@ -593,7 +593,7 @@ void LimitedNodeList::eraseAllNodes() { QWriteLocker writeLocker(&_nodeMutex); if (_nodeHash.size() > 0) { - qCDebug(networking) << "LimitedNodeList::eraseAllNodes() removing all nodes from NodeList."; + qCDebug(networking) << "LimitedNodeList::eraseAllNodes() removing all nodes from NodeList:" << reason; killedNodes.reserve(_nodeHash.size()); for (auto& pair : _nodeHash) { @@ -611,8 +611,8 @@ void LimitedNodeList::eraseAllNodes() { _delayedNodeAdds.clear(); } -void LimitedNodeList::reset() { - eraseAllNodes(); +void LimitedNodeList::reset(QString reason) { + eraseAllNodes(reason); // we need to make sure any socket connections are gone so wait on that here _nodeSocket.clearConnections(); @@ -754,6 +754,7 @@ SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t connect(newNodePointer.data(), &NetworkPeer::socketUpdated, this, [this, weakPtr] { emit nodeSocketUpdated(weakPtr); }); + connect(newNodePointer.data(), &NetworkPeer::socketUpdated, &_nodeSocket, &udt::Socket::handleRemoteAddressChange); return newNodePointer; } @@ -1088,12 +1089,14 @@ void LimitedNodeList::processSTUNResponse(std::unique_ptr packe if (parseSTUNResponse(packet.get(), newPublicAddress, newPublicPort)) { if (newPublicAddress != _publicSockAddr.getAddress() || newPublicPort != _publicSockAddr.getPort()) { - _publicSockAddr = HifiSockAddr(newPublicAddress, newPublicPort); - - qCDebug(networking, "New public socket received from STUN server is %s:%hu", + qCDebug(networking, "New public socket received from STUN server is %s:%hu (was %s:%hu)", + newPublicAddress.toString().toStdString().c_str(), + newPublicPort, _publicSockAddr.getAddress().toString().toLocal8Bit().constData(), _publicSockAddr.getPort()); + _publicSockAddr = HifiSockAddr(newPublicAddress, newPublicPort); + if (!_hasCompletedInitialSTUN) { // if we're here we have definitely completed our initial STUN sequence stopInitialSTUNUpdate(true); @@ -1255,7 +1258,7 @@ void LimitedNodeList::setLocalSocket(const HifiSockAddr& sockAddr) { qCInfo(networking) << "Local socket has changed from" << _localSockAddr << "to" << sockAddr; _localSockAddr = sockAddr; if (_hasTCPCheckedLocalSocket) { // Force a port change for NAT: - reset(); + reset("local socket change"); _nodeSocket.rebind(0); _localSockAddr.setPort(_nodeSocket.localPort()); qCInfo(networking) << "Local port changed to" << _localSockAddr.getPort(); diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 5f24401b10..a61deeef96 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -111,7 +111,8 @@ public: enum ConnectReason : quint32 { Connect = 0, - SilentDomainDisconnect + SilentDomainDisconnect, + Awake }; Q_ENUM(ConnectReason); @@ -347,8 +348,8 @@ public: }; public slots: - void reset(); - void eraseAllNodes(); + void reset(QString reason); + void eraseAllNodes(QString reason); void removeSilentNodes(); @@ -358,6 +359,7 @@ public slots: virtual void sendSTUNRequest(); bool killNodeWithUUID(const QUuid& nodeUUID, ConnectionID newConnectionID = NULL_CONNECTION_ID); + void noteAwakening() { _connectReason = Awake; } private slots: void sampleConnectionStats(); diff --git a/libraries/networking/src/NetworkPeer.cpp b/libraries/networking/src/NetworkPeer.cpp index 4e0a82ba0e..a48922726e 100644 --- a/libraries/networking/src/NetworkPeer.cpp +++ b/libraries/networking/src/NetworkPeer.cpp @@ -59,13 +59,13 @@ void NetworkPeer::setPublicSocket(const HifiSockAddr& publicSocket) { bool wasOldSocketNull = _publicSocket.isNull(); - auto temp = _publicSocket.objectName(); + auto previousSocket = _publicSocket; _publicSocket = publicSocket; - _publicSocket.setObjectName(temp); + _publicSocket.setObjectName(previousSocket.objectName()); if (!wasOldSocketNull) { - qCDebug(networking) << "Public socket change for node" << *this; - emit socketUpdated(); + qCDebug(networking) << "Public socket change for node" << *this << "; previously" << previousSocket; + emit socketUpdated(previousSocket, _publicSocket); } } } @@ -79,13 +79,13 @@ void NetworkPeer::setLocalSocket(const HifiSockAddr& localSocket) { bool wasOldSocketNull = _localSocket.isNull(); - auto temp = _localSocket.objectName(); + auto previousSocket = _localSocket; _localSocket = localSocket; - _localSocket.setObjectName(temp); + _localSocket.setObjectName(previousSocket.objectName()); if (!wasOldSocketNull) { - qCDebug(networking) << "Local socket change for node" << *this; - emit socketUpdated(); + qCDebug(networking) << "Local socket change for node" << *this << "; previously" << previousSocket; + emit socketUpdated(previousSocket, _localSocket); } } } @@ -99,13 +99,13 @@ void NetworkPeer::setSymmetricSocket(const HifiSockAddr& symmetricSocket) { bool wasOldSocketNull = _symmetricSocket.isNull(); - auto temp = _symmetricSocket.objectName(); + auto previousSocket = _symmetricSocket; _symmetricSocket = symmetricSocket; - _symmetricSocket.setObjectName(temp); + _symmetricSocket.setObjectName(previousSocket.objectName()); if (!wasOldSocketNull) { - qCDebug(networking) << "Symmetric socket change for node" << *this; - emit socketUpdated(); + qCDebug(networking) << "Symmetric socket change for node" << *this << "; previously" << previousSocket; + emit socketUpdated(previousSocket, _symmetricSocket); } } } diff --git a/libraries/networking/src/NetworkPeer.h b/libraries/networking/src/NetworkPeer.h index e2149d64af..4c08c97d3c 100644 --- a/libraries/networking/src/NetworkPeer.h +++ b/libraries/networking/src/NetworkPeer.h @@ -94,7 +94,7 @@ public slots: signals: void pingTimerTimeout(); void socketActivated(const HifiSockAddr& sockAddr); - void socketUpdated(); + void socketUpdated(HifiSockAddr previousAddress, HifiSockAddr currentAddress); protected: void setActiveSocket(HifiSockAddr* discoveredSocket); diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 9dd7716823..306e0155d3 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -116,7 +116,11 @@ NodeList::NodeList(char newOwnerType, int socketListenPort, int dtlsListenPort) connect(&_domainHandler, SIGNAL(connectedToDomain(QUrl)), &_keepAlivePingTimer, SLOT(start())); connect(&_domainHandler, &DomainHandler::disconnectedFromDomain, &_keepAlivePingTimer, &QTimer::stop); - connect(&_domainHandler, &DomainHandler::limitOfSilentDomainCheckInsReached, this, [this]() { _connectReason = LimitedNodeList::SilentDomainDisconnect; }); + connect(&_domainHandler, &DomainHandler::limitOfSilentDomainCheckInsReached, this, [this]() { + if (_connectReason != Awake) { + _connectReason = SilentDomainDisconnect; + } + }); // set our sockAddrBelongsToDomainOrNode method as the connection creation filter for the udt::Socket using std::placeholders::_1; @@ -259,8 +263,7 @@ void NodeList::reset(QString reason, bool skipDomainHandlerReset) { Q_ARG(bool, skipDomainHandlerReset)); return; } - - LimitedNodeList::reset(); + LimitedNodeList::reset(reason); // lock and clear our set of ignored IDs _ignoredSetLock.lockForWrite(); @@ -337,7 +340,8 @@ void NodeList::sendDomainServerCheckIn() { if (!domainIsConnected) { auto hostname = _domainHandler.getHostname(); - qCDebug(networking_ice) << "Sending connect request to domain-server at" << hostname; + QMetaEnum metaEnum = QMetaEnum::fromType(); + qCDebug(networking_ice) << "Sending connect request ( REASON:" << QString(metaEnum.valueToKey(_connectReason)) << ") to domain-server at" << hostname; // is this our localhost domain-server? // if so we need to make sure we have an up-to-date local port in case it restarted diff --git a/libraries/networking/src/RSAKeypairGenerator.cpp b/libraries/networking/src/RSAKeypairGenerator.cpp index e83615e3df..df04297383 100644 --- a/libraries/networking/src/RSAKeypairGenerator.cpp +++ b/libraries/networking/src/RSAKeypairGenerator.cpp @@ -28,6 +28,7 @@ RSAKeypairGenerator::RSAKeypairGenerator(QObject* parent) : } void RSAKeypairGenerator::run() { + qCDebug(networking) << "KEYPAIR: thread started"; generateKeypair(); } @@ -53,6 +54,7 @@ void RSAKeypairGenerator::generateKeypair() { BN_free(exponent); return; } + qCDebug(networking) << "KEYPAIR: OpenSSL generated a" << RSA_KEY_BITS << "bit RSA key-pair"; // we don't need the BIGNUM anymore so clean that up BN_free(exponent); @@ -95,5 +97,6 @@ void RSAKeypairGenerator::generateKeypair() { OPENSSL_free(publicKeyDER); OPENSSL_free(privateKeyDER); + qCDebug(networking) << "KEYPAIR: emitting generated signal and finishing"; emit generatedKeypair(_publicKey, _privateKey); } diff --git a/libraries/networking/src/udt/Connection.cpp b/libraries/networking/src/udt/Connection.cpp index 418dc8f417..872ee4dd4c 100644 --- a/libraries/networking/src/udt/Connection.cpp +++ b/libraries/networking/src/udt/Connection.cpp @@ -114,6 +114,7 @@ SendQueue& Connection::getSendQueue() { QObject::connect(_sendQueue.get(), &SendQueue::packetRetransmitted, this, &Connection::recordRetransmission); QObject::connect(_sendQueue.get(), &SendQueue::queueInactive, this, &Connection::queueInactive); QObject::connect(_sendQueue.get(), &SendQueue::timeout, this, &Connection::queueTimeout); + QObject::connect(this, &Connection::destinationAddressChange, _sendQueue.get(), &SendQueue::updateDestinationAddress); // set defaults on the send queue from our congestion control object and estimatedTimeout() @@ -485,3 +486,10 @@ std::unique_ptr PendingReceivedMessage::removeNextPacket() { } return std::unique_ptr(); } + +void Connection::setDestinationAddress(const HifiSockAddr& destination) { + if (_destination != destination) { + _destination = destination; + emit destinationAddressChange(destination); + } +} diff --git a/libraries/networking/src/udt/Connection.h b/libraries/networking/src/udt/Connection.h index 938ec36860..47edb021c8 100644 --- a/libraries/networking/src/udt/Connection.h +++ b/libraries/networking/src/udt/Connection.h @@ -76,10 +76,12 @@ public: void recordSentUnreliablePackets(int wireSize, int payloadSize); void recordReceivedUnreliablePackets(int wireSize, int payloadSize); + void setDestinationAddress(const HifiSockAddr& destination); signals: void packetSent(); void receiverHandshakeRequestComplete(const HifiSockAddr& sockAddr); + void destinationAddressChange(HifiSockAddr currentAddress); private slots: void recordSentPackets(int wireSize, int payloadSize, SequenceNumber seqNum, p_high_resolution_clock::time_point timePoint); diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 6230b8b11e..736296a2d6 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -271,6 +271,7 @@ enum class EntityVersion : PacketVersion { ParticleShapeType, ParticleShapeTypeDeadlockFix, PrivateUserData, + TextUnlit, // Add new versions above here NUM_PACKET_TYPE, diff --git a/libraries/networking/src/udt/SendQueue.cpp b/libraries/networking/src/udt/SendQueue.cpp index 15841b5c21..2997c272f9 100644 --- a/libraries/networking/src/udt/SendQueue.cpp +++ b/libraries/networking/src/udt/SendQueue.cpp @@ -557,3 +557,7 @@ void SendQueue::deactivate() { bool SendQueue::isFlowWindowFull() const { return seqlen(SequenceNumber { (uint32_t) _lastACKSequenceNumber }, _currentSequenceNumber) > _flowWindowSize; } + +void SendQueue::updateDestinationAddress(HifiSockAddr newAddress) { + _destination = newAddress; +} diff --git a/libraries/networking/src/udt/SendQueue.h b/libraries/networking/src/udt/SendQueue.h index c1a2b59075..2153745250 100644 --- a/libraries/networking/src/udt/SendQueue.h +++ b/libraries/networking/src/udt/SendQueue.h @@ -75,6 +75,7 @@ public slots: void ack(SequenceNumber ack); void fastRetransmit(SequenceNumber ack); void handshakeACK(); + void updateDestinationAddress(HifiSockAddr newAddress); signals: void packetSent(int wireSize, int payloadSize, SequenceNumber seqNum, p_high_resolution_clock::time_point timePoint); diff --git a/libraries/networking/src/udt/Socket.cpp b/libraries/networking/src/udt/Socket.cpp index c56f276560..4714160ace 100644 --- a/libraries/networking/src/udt/Socket.cpp +++ b/libraries/networking/src/udt/Socket.cpp @@ -538,6 +538,33 @@ void Socket::handleStateChanged(QAbstractSocket::SocketState socketState) { } } +void Socket::handleRemoteAddressChange(HifiSockAddr previousAddress, HifiSockAddr currentAddress) { + { + Lock connectionsLock(_connectionsHashMutex); + _connectionsHash.erase(currentAddress); + + const auto connectionIter = _connectionsHash.find(previousAddress); + if (connectionIter != _connectionsHash.end()) { + auto connection = move(connectionIter->second); + _connectionsHash.erase(connectionIter); + connection->setDestinationAddress(currentAddress); + _connectionsHash[currentAddress] = move(connection); + } + } + + { + Lock sequenceNumbersLock(_unreliableSequenceNumbersMutex); + _unreliableSequenceNumbers.erase(currentAddress); + + const auto sequenceNumbersIter = _unreliableSequenceNumbers.find(previousAddress); + if (sequenceNumbersIter != _unreliableSequenceNumbers.end()) { + auto sequenceNumbers = sequenceNumbersIter->second; + _unreliableSequenceNumbers.erase(sequenceNumbersIter); + _unreliableSequenceNumbers[currentAddress] = sequenceNumbers; + } + } +} + #if (PR_BUILD || DEV_BUILD) void Socket::sendFakedHandshakeRequest(const HifiSockAddr& sockAddr) { diff --git a/libraries/networking/src/udt/Socket.h b/libraries/networking/src/udt/Socket.h index ad9d6de8b8..6cd2d25659 100644 --- a/libraries/networking/src/udt/Socket.h +++ b/libraries/networking/src/udt/Socket.h @@ -99,7 +99,8 @@ signals: public slots: void cleanupConnection(HifiSockAddr sockAddr); void clearConnections(); - + void handleRemoteAddressChange(HifiSockAddr previousAddress, HifiSockAddr currentAddress); + private slots: void readPendingDatagrams(); void checkForReadyReadBackup(); @@ -110,7 +111,6 @@ private slots: private: void setSystemBufferSizes(); Connection* findOrCreateConnection(const HifiSockAddr& sockAddr, bool filterCreation = false); - bool socketMatchesNodeOrDomain(const HifiSockAddr& sockAddr); // privatized methods used by UDTTest - they are private since they must be called on the Socket thread ConnectionStats::Stats sampleStatsForConnection(const HifiSockAddr& destination); diff --git a/libraries/physics/src/ObjectActionOffset.cpp b/libraries/physics/src/ObjectActionOffset.cpp index a99c875106..526eb9f000 100644 --- a/libraries/physics/src/ObjectActionOffset.cpp +++ b/libraries/physics/src/ObjectActionOffset.cpp @@ -143,8 +143,8 @@ bool ObjectActionOffset::updateArguments(QVariantMap arguments) { } /**jsdoc - * The "offset" {@link Entities.ActionType|ActionType} moves an entity so that it is a set distance away from a - * target point. + * The "offset" {@link Entities.ActionType|ActionType} moves an entity so that it is a defined distance away from + * a target point. * It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}: * * @typedef {object} Entities.ActionArguments-Offset diff --git a/libraries/physics/src/ObjectDynamic.cpp b/libraries/physics/src/ObjectDynamic.cpp index f02b7b1c4c..4f7feacbab 100644 --- a/libraries/physics/src/ObjectDynamic.cpp +++ b/libraries/physics/src/ObjectDynamic.cpp @@ -95,23 +95,24 @@ bool ObjectDynamic::updateArguments(QVariantMap arguments) { /**jsdoc * Different entity action types have different arguments: some common to all actions (listed in the table) and some specific - * to each {@link Entities.ActionType|ActionType} (linked to below). The arguments are accessed as an object of property names - * and values. + * to each {@link Entities.ActionType|ActionType} (linked to below). * * @typedef {object} Entities.ActionArguments * @property {Entities.ActionType} type - The type of action. * @property {string} tag="" - A string that a script can use for its own purposes. * @property {number} ttl=0 - How long the action should exist, in seconds, before it is automatically deleted. A value of * 0 means that the action should not be deleted. - * @property {boolean} isMine=true - Is true if the action was created during the current client session, - * false otherwise. Read-only. - * @property {boolean} ::no-motion-state - Is present when the entity hasn't been registered with the physics engine yet (e.g., - * if the action hasn't been properly configured), otherwise undefined. Read-only. - * @property {boolean} ::active - Is true when the action is modifying the entity's motion, false - * otherwise. Is present once the entity has been registered with the physics engine, otherwise undefined. + * @property {boolean} isMine=true - true if the action was created during the current client session, + * false if it wasn't. Read-only. + * @property {boolean} ::no-motion-state - Is present with a value of true when the entity hasn't been registered + * with the physics engine yet (e.g., if the action hasn't been properly configured), otherwise the property is + * undefined. Read-only. + * @property {boolean} ::active - true when the action is modifying the entity's motion, false + * otherwise. Is present once the entity has been registered with the physics engine, otherwise the property is + * undefined. * Read-only. * @property {Entities.PhysicsMotionType} ::motion-type - How the entity moves with the action. Is present once the entity has - * been registered with the physics engine, otherwise undefined. Read-only. + * been registered with the physics engine, otherwise the property is undefined. Read-only. * * @comment The different action types have additional arguments as follows: * @see {@link Entities.ActionArguments-FarGrab|ActionArguments-FarGrab} diff --git a/libraries/platform/CMakeLists.txt b/libraries/platform/CMakeLists.txt index 55203d45a4..f0dce500f4 100644 --- a/libraries/platform/CMakeLists.txt +++ b/libraries/platform/CMakeLists.txt @@ -12,4 +12,7 @@ if (APPLE) find_library(AppKit AppKit) target_link_libraries(${TARGET_NAME} ${OpenGL} ${AppKit}) -endif () + +elseif(WIN32) + target_link_libraries(${TARGET_NAME} Iphlpapi.lib) +endif () \ No newline at end of file diff --git a/libraries/platform/src/platform/Platform.h b/libraries/platform/src/platform/Platform.h index 9405c77ae0..8cda6332ee 100644 --- a/libraries/platform/src/platform/Platform.h +++ b/libraries/platform/src/platform/Platform.h @@ -21,12 +21,15 @@ bool enumeratePlatform(); int getNumCPUs(); json getCPU(int index); +int getMasterCPU(); int getNumGPUs(); json getGPU(int index); +int getMasterGPU(); int getNumDisplays(); json getDisplay(int index); +int getMasterDisplay(); json getMemory(); diff --git a/libraries/platform/src/platform/PlatformKeys.h b/libraries/platform/src/platform/PlatformKeys.h index 1008c5ca4b..5008a4f6ce 100644 --- a/libraries/platform/src/platform/PlatformKeys.h +++ b/libraries/platform/src/platform/PlatformKeys.h @@ -20,6 +20,7 @@ namespace platform { namespace keys{ extern const char* model; extern const char* clockSpeed; extern const char* numCores; + extern const char* isMaster; } namespace gpu { extern const char* vendor; @@ -30,14 +31,29 @@ namespace platform { namespace keys{ extern const char* model; extern const char* videoMemory; extern const char* driver; + extern const char* displays; + extern const char* isMaster; + } + namespace nic { + extern const char* mac; + extern const char* name; } namespace display { extern const char* description; extern const char* name; - extern const char* coordsLeft; - extern const char* coordsRight; - extern const char* coordsTop; - extern const char* coordsBottom; + extern const char* boundsLeft; + extern const char* boundsRight; + extern const char* boundsTop; + extern const char* boundsBottom; + extern const char* gpu; + extern const char* ppi; + extern const char* ppiDesktop; + extern const char* physicalWidth; + extern const char* physicalHeight; + extern const char* modeRefreshrate; + extern const char* modeWidth; + extern const char* modeHeight; + extern const char* isMaster; } namespace memory { extern const char* memTotal; @@ -63,6 +79,7 @@ namespace platform { namespace keys{ extern const char* CPUS; extern const char* GPUS; extern const char* DISPLAYS; + extern const char* NICS; extern const char* MEMORY; extern const char* COMPUTER; diff --git a/libraries/platform/src/platform/Profiler.cpp b/libraries/platform/src/platform/Profiler.cpp index 1c055a5ec9..3e4dff9fd1 100644 --- a/libraries/platform/src/platform/Profiler.cpp +++ b/libraries/platform/src/platform/Profiler.cpp @@ -32,9 +32,9 @@ Profiler::Tier Profiler::profilePlatform() { return platformTier; } - // Not filtered yet, let s try to make sense of the cpu and gpu info - auto cpuInfo = platform::getCPU(0); - auto gpuInfo = platform::getGPU(0); + // Not filtered yet, let s try to make sense of the master cpu and master gpu info + auto cpuInfo = platform::getCPU(platform::getMasterCPU()); + auto gpuInfo = platform::getGPU(platform::getMasterGPU()); if (filterOnProcessors(computerInfo, cpuInfo, gpuInfo, platformTier)) { return platformTier; } @@ -133,10 +133,12 @@ bool filterOnProcessors(const platform::json& computer, const platform::json& cp // YES on macos EXCEPT for macbookair with gpu intel iris or intel HD 6000 bool Profiler::isRenderMethodDeferredCapable() { #if defined(Q_OS_MAC) + // Deferred works correctly on every supported macos platform at the moment, let s enable it +/* auto computer = platform::getComputer(); const auto computerModel = (computer.count(keys::computer::model) ? computer[keys::computer::model].get() : ""); - auto gpuInfo = platform::getGPU(0); + auto gpuInfo = platform::getGPU(getMasterGPU()); const auto gpuModel = (gpuInfo.count(keys::gpu::model) ? gpuInfo[keys::gpu::model].get() : ""); @@ -154,7 +156,7 @@ bool Profiler::isRenderMethodDeferredCapable() { if ((gpuModel.find("Intel ") != std::string::npos)) { return false; } - +*/ return true; #elif defined(Q_OS_ANDROID) return false; diff --git a/libraries/platform/src/platform/backend/AndroidPlatform.cpp b/libraries/platform/src/platform/backend/AndroidPlatform.cpp index b0a4c5e67b..4487d305cf 100644 --- a/libraries/platform/src/platform/backend/AndroidPlatform.cpp +++ b/libraries/platform/src/platform/backend/AndroidPlatform.cpp @@ -10,6 +10,7 @@ #include "../PlatformKeys.h" #include #include +#include using namespace platform; @@ -23,7 +24,7 @@ void AndroidInstance::enumerateCpus() { _cpus.push_back(cpu); } -void AndroidInstance::enumerateGpus() { +void AndroidInstance::enumerateGpusAndDisplays() { GPUIdent* ident = GPUIdent::getInstance(); json gpu = {}; gpu[keys::gpu::model] = ident->getName().toUtf8().constData(); diff --git a/libraries/platform/src/platform/backend/AndroidPlatform.h b/libraries/platform/src/platform/backend/AndroidPlatform.h index 6592b3519d..488f564057 100644 --- a/libraries/platform/src/platform/backend/AndroidPlatform.h +++ b/libraries/platform/src/platform/backend/AndroidPlatform.h @@ -16,7 +16,7 @@ namespace platform { public: void enumerateCpus() override; - void enumerateGpus() override; + void enumerateGpusAndDisplays() override; void enumerateMemory() override; void enumerateComputer() override; }; diff --git a/libraries/platform/src/platform/backend/LinuxPlatform.cpp b/libraries/platform/src/platform/backend/LinuxPlatform.cpp index 61501669cb..eb2c8d4259 100644 --- a/libraries/platform/src/platform/backend/LinuxPlatform.cpp +++ b/libraries/platform/src/platform/backend/LinuxPlatform.cpp @@ -12,6 +12,9 @@ #include #include #include + +#include + #include #include @@ -27,7 +30,7 @@ void LinuxInstance::enumerateCpus() { _cpus.push_back(cpu); } -void LinuxInstance::enumerateGpus() { +void LinuxInstance::enumerateGpusAndDisplays() { GPUIdent* ident = GPUIdent::getInstance(); json gpu = {}; gpu[keys::gpu::model] = ident->getName().toUtf8().constData(); diff --git a/libraries/platform/src/platform/backend/LinuxPlatform.h b/libraries/platform/src/platform/backend/LinuxPlatform.h index 2f2529db7c..0d2e567e0b 100644 --- a/libraries/platform/src/platform/backend/LinuxPlatform.h +++ b/libraries/platform/src/platform/backend/LinuxPlatform.h @@ -16,7 +16,7 @@ namespace platform { public: void enumerateCpus() override; - void enumerateGpus() override; + void enumerateGpusAndDisplays() override; void enumerateMemory() override; void enumerateComputer() override; }; diff --git a/libraries/platform/src/platform/backend/MACOSPlatform.cpp b/libraries/platform/src/platform/backend/MACOSPlatform.cpp index cacbd06816..66c9cd2c5d 100644 --- a/libraries/platform/src/platform/backend/MACOSPlatform.cpp +++ b/libraries/platform/src/platform/backend/MACOSPlatform.cpp @@ -12,16 +12,22 @@ #include #include #include -#include + +#include #ifdef Q_OS_MAC #include #include #include +#include +#include + #include #include #include +#include +#include #endif using namespace platform; @@ -36,73 +42,249 @@ void MACOSInstance::enumerateCpus() { _cpus.push_back(cpu); } -void MACOSInstance::enumerateGpus() { + +void MACOSInstance::enumerateGpusAndDisplays() { #ifdef Q_OS_MAC + // ennumerate the displays first + std::vector displayMasks; + { + uint32_t numDisplays = 0; + CGError error = CGGetOnlineDisplayList(0, nullptr, &numDisplays); + if (numDisplays <= 0 || error != kCGErrorSuccess) { + return; + } - GPUIdent* ident = GPUIdent::getInstance(); - json gpu = {}; + std::vector onlineDisplayIDs(numDisplays, 0); + error = CGGetOnlineDisplayList(onlineDisplayIDs.size(), onlineDisplayIDs.data(), &numDisplays); + if (error != kCGErrorSuccess) { + return; + } - gpu[keys::gpu::model] = ident->getName().toUtf8().constData(); - gpu[keys::gpu::vendor] = findGPUVendorInDescription(gpu[keys::gpu::model].get()); - gpu[keys::gpu::videoMemory] = ident->getMemory(); - gpu[keys::gpu::driver] = ident->getDriver().toUtf8().constData(); - - _gpus.push_back(gpu); + for (auto displayID : onlineDisplayIDs) { + auto displaySize = CGDisplayScreenSize(displayID); + const auto MM_TO_IN = 0.0393701f; + auto displaySizeWidthInches = displaySize.width * MM_TO_IN; + auto displaySizeHeightInches = displaySize.height * MM_TO_IN; + + auto displayBounds = CGDisplayBounds(displayID); + auto displayMaster =CGDisplayIsMain(displayID); + + auto displayUnit =CGDisplayUnitNumber(displayID); + auto displayModel =CGDisplayModelNumber(displayID); + auto displayVendor = CGDisplayVendorNumber(displayID); + auto displaySerial = CGDisplaySerialNumber(displayID); + + auto displayMode = CGDisplayCopyDisplayMode(displayID); + auto displayModeWidth = CGDisplayModeGetPixelWidth(displayMode); + auto displayModeHeight = CGDisplayModeGetPixelHeight(displayMode); + auto displayRefreshrate = CGDisplayModeGetRefreshRate(displayMode); + + auto ppiH = displayModeWidth / displaySizeWidthInches; + auto ppiV = displayModeHeight / displaySizeHeightInches; + + auto ppiHScaled = displayBounds.size.width / displaySizeWidthInches; + auto ppiVScaled = displayBounds.size.height / displaySizeHeightInches; + + auto glmask = CGDisplayIDToOpenGLDisplayMask(displayID); + // Metal device ID is the recommended new way but requires objective c + // auto displayDevice = CGDirectDisplayCopyCurrentMetalDevice(displayID); + + CGDisplayModeRelease(displayMode); + + json display = {}; + + // Rect region of the desktop in desktop units + display[keys::display::boundsLeft] = displayBounds.origin.x; + display[keys::display::boundsRight] = displayBounds.origin.x + displayBounds.size.width; + display[keys::display::boundsTop] = displayBounds.origin.y; + display[keys::display::boundsBottom] = displayBounds.origin.y + displayBounds.size.height; + + // PPI & resolution + display[keys::display::physicalWidth] = displaySizeWidthInches; + display[keys::display::physicalHeight] = displaySizeHeightInches; + display[keys::display::modeWidth] = displayModeWidth; + display[keys::display::modeHeight] = displayModeHeight; + + //Average the ppiH and V for the simple ppi + display[keys::display::ppi] = std::round(0.5f * (ppiH + ppiV)); + display[keys::display::ppiDesktop] = std::round(0.5f * (ppiHScaled + ppiVScaled)); + + // refreshrate + display[keys::display::modeRefreshrate] = displayRefreshrate; + + // Master display ? + display[keys::display::isMaster] = (displayMaster ? true : false); + + // Macos specific + display["macos_unit"] = displayUnit; + display["macos_vendor"] = displayVendor; + display["macos_model"] = displayModel; + display["macos_serial"] = displaySerial; + display["macos_glmask"] = glmask; + displayMasks.push_back(glmask); + + _displays.push_back(display); + } + } -#endif + // Collect Renderer info as exposed by the CGL layers + GLuint cglDisplayMask = -1; // Iterate over all of them. + CGLRendererInfoObj rendererInfo; + GLint rendererInfoCount; + CGLError error = CGLQueryRendererInfo(cglDisplayMask, &rendererInfo, &rendererInfoCount); + if (rendererInfoCount <= 0 || 0 != error) { + return; + } + + // Iterate over all of the renderers and use the figure for the one with the most VRAM, + // on the assumption that this is the one that will actually be used. + for (GLint i = 0; i < rendererInfoCount; i++) { + struct CGLRendererDesc { + int rendererID{0}; + int deviceVRAM{0}; + int accelerated{0}; + int displayMask{0}; + } desc; + + CGLDescribeRenderer(rendererInfo, i, kCGLRPRendererID, &desc.rendererID); + CGLDescribeRenderer(rendererInfo, i, kCGLRPVideoMemoryMegabytes, &desc.deviceVRAM); + CGLDescribeRenderer(rendererInfo, i, kCGLRPDisplayMask, &desc.displayMask); + CGLDescribeRenderer(rendererInfo, i, kCGLRPAccelerated, &desc.accelerated); + + // If this renderer is not hw accelerated then just skip it in the enumeration + if (!desc.accelerated) { + continue; + } + + // From the rendererID identify the vendorID + // https://github.com/apitrace/apitrace/blob/master/retrace/glws_cocoa.mm + GLint vendorID = desc.rendererID & kCGLRendererIDMatchingMask & ~0xfff; + const GLint VENDOR_ID_SOFTWARE { 0x00020000 }; + const GLint VENDOR_ID_AMD { 0x00021000 }; + const GLint VENDOR_ID_NVIDIA { 0x00022000 }; + const GLint VENDOR_ID_INTEL { 0x00024000 }; + + const char* vendorName; + switch (vendorID) { + case VENDOR_ID_SOFTWARE: + // Software renderer then skip it (should already have been caught by hwaccelerated test abve + continue; + break; + case VENDOR_ID_AMD: + vendorName = keys::gpu::vendor_AMD; + break; + case VENDOR_ID_NVIDIA: + vendorName = keys::gpu::vendor_NVIDIA; + break; + case VENDOR_ID_INTEL: + vendorName = keys::gpu::vendor_Intel; + break; + default: + vendorName = keys::UNKNOWN; + break; + } + + //once we reach this point, the renderer is legit + // Start defining the gpu json + json gpu = {}; + gpu[keys::gpu::vendor] = vendorName; + gpu[keys::gpu::videoMemory] = desc.deviceVRAM; + gpu["macos_rendererID"] = desc.rendererID; + gpu["macos_displayMask"] = desc.displayMask; + + std::vector displayIndices; + for (int d = 0; d < (int) displayMasks.size(); d++) { + if (desc.displayMask & displayMasks[d]) { + displayIndices.push_back(d); + _displays[d][keys::display::gpu] = _gpus.size(); + } + } + gpu[keys::gpu::displays] = displayIndices; + + _gpus.push_back(gpu); + } + + CGLDestroyRendererInfo(rendererInfo); + + + { //get gpu information from the system profiler that we don't know how to retreive otherwise + struct ChipsetModelDesc { + std::string model; + std::string vendor; + int deviceID{0}; + int videoMemory{0}; + }; + std::vector chipsetDescs; + FILE* stream = popen("system_profiler SPDisplaysDataType | grep -e Chipset -e VRAM -e Vendor -e \"Device ID\"", "r"); + std::ostringstream hostStream; + while (!feof(stream) && !ferror(stream)) { + char buf[128]; + int bytesRead = fread(buf, 1, 128, stream); + hostStream.write(buf, bytesRead); + } + std::string gpuArrayDesc = hostStream.str(); + + // Find the Chipset model first + const std::regex chipsetModelToken("(Chipset Model: )(.*)"); + std::smatch found; + + while (std::regex_search(gpuArrayDesc, found, chipsetModelToken)) { + ChipsetModelDesc desc; -} - -void MACOSInstance::enumerateDisplays() { -#ifdef Q_OS_MAC - auto displayID = CGMainDisplayID(); - auto displaySize = CGDisplayScreenSize(displayID); - - const auto MM_TO_IN = 0.0393701; - auto displaySizeWidthInches = displaySize.width * MM_TO_IN; - auto displaySizeHeightInches = displaySize.height * MM_TO_IN; - auto displaySizeDiagonalInches = sqrt(displaySizeWidthInches * displaySizeWidthInches + displaySizeHeightInches * displaySizeHeightInches); + desc.model = found.str(2); + + // Find the end of the gpu block + gpuArrayDesc = found.suffix(); + std::string gpuDesc = gpuArrayDesc; + const std::regex endGpuToken("Chipset Model: "); + if (std::regex_search(gpuArrayDesc, found, endGpuToken)) { + gpuDesc = found.prefix(); + } + + // Find the vendor + desc.vendor = findGPUVendorInDescription(desc.model); + + // Find the memory amount in MB + const std::regex memoryToken("(VRAM .*: )(.*)"); + if (std::regex_search(gpuDesc, found, memoryToken)) { + auto memAmountUnit = found.str(2); + std::smatch amount; + const std::regex memAmountGBToken("(\\d*) GB"); + const std::regex memAmountMBToken("(\\d*) MB"); + const int GB_TO_MB { 1024 }; + if (std::regex_search(memAmountUnit, amount, memAmountGBToken)) { + desc.videoMemory = std::stoi(amount.str(1)) * GB_TO_MB; + } else if (std::regex_search(memAmountUnit, amount, memAmountMBToken)) { + desc.videoMemory = std::stoi(amount.str(1)); + } else { + desc.videoMemory = std::stoi(memAmountUnit); + } + } + + // Find the Device ID + const std::regex deviceIDToken("(Device ID: )(.*)"); + if (std::regex_search(gpuDesc, found, deviceIDToken)) { + desc.deviceID = std::stoi(found.str(2), 0, 16); + } + + chipsetDescs.push_back(desc); + } + + // GO through the detected gpus in order and complete missing information from ChipsetModelDescs + // assuming the order is the same and checking that the vendor and memory amount match as a simple check + auto numDescs = (int) std::min(chipsetDescs.size(),_gpus.size()); + for (int i = 0; i < numDescs; ++i) { + const auto& chipset = chipsetDescs[i]; + auto& gpu = _gpus[i]; + + if ( (chipset.vendor.find( gpu[keys::gpu::vendor]) != std::string::npos) + && (chipset.videoMemory == gpu[keys::gpu::videoMemory]) ) { + gpu[keys::gpu::model] = chipset.model; + gpu["macos_deviceID"] = chipset.deviceID; + } + } + } - auto displayBounds = CGDisplayBounds(displayID); - auto displayMaster =CGDisplayIsMain(displayID); - - auto displayUnit =CGDisplayUnitNumber(displayID); - auto displayModel =CGDisplayModelNumber(displayID); - auto displayVendor = CGDisplayVendorNumber(displayID); - auto displaySerial = CGDisplaySerialNumber(displayID); - - auto displayMode = CGDisplayCopyDisplayMode(displayID); - auto displayModeWidth = CGDisplayModeGetPixelWidth(displayMode); - auto displayModeHeight = CGDisplayModeGetPixelHeight(displayMode); - auto displayRefreshrate = CGDisplayModeGetRefreshRate(displayMode); - - CGDisplayModeRelease(displayMode); - - json display = {}; - - display["physicalWidth"] = displaySizeWidthInches; - display["physicalHeight"] = displaySizeHeightInches; - display["physicalDiagonal"] = displaySizeDiagonalInches; - - display["ppi"] = sqrt(displayModeHeight * displayModeHeight + displayModeWidth * displayModeWidth) / displaySizeDiagonalInches; - - display["coordLeft"] = displayBounds.origin.x; - display["coordRight"] = displayBounds.origin.x + displayBounds.size.width; - display["coordTop"] = displayBounds.origin.y; - display["coordBottom"] = displayBounds.origin.y + displayBounds.size.height; - - display["isMaster"] = displayMaster; - - display["unit"] = displayUnit; - display["vendor"] = displayVendor; - display["model"] = displayModel; - display["serial"] = displaySerial; - - display["refreshrate"] =displayRefreshrate; - display["modeWidth"] = displayModeWidth; - display["modeHeight"] = displayModeHeight; - - _displays.push_back(display); #endif } @@ -132,11 +314,11 @@ void MACOSInstance::enumerateComputer(){ _computer[keys::computer::model]=std::string(model); free(model); - -#endif auto sysInfo = QSysInfo(); _computer[keys::computer::OSVersion] = sysInfo.kernelVersion().toStdString(); +#endif + } diff --git a/libraries/platform/src/platform/backend/MACOSPlatform.h b/libraries/platform/src/platform/backend/MACOSPlatform.h index e893dda739..f249dad001 100644 --- a/libraries/platform/src/platform/backend/MACOSPlatform.h +++ b/libraries/platform/src/platform/backend/MACOSPlatform.h @@ -16,8 +16,7 @@ namespace platform { public: void enumerateCpus() override; - void enumerateGpus() override; - void enumerateDisplays() override; + void enumerateGpusAndDisplays() override; void enumerateMemory() override; void enumerateComputer() override; }; diff --git a/libraries/platform/src/platform/backend/Platform.cpp b/libraries/platform/src/platform/backend/Platform.cpp index dba41ce121..17d9d8019e 100644 --- a/libraries/platform/src/platform/backend/Platform.cpp +++ b/libraries/platform/src/platform/backend/Platform.cpp @@ -21,7 +21,8 @@ namespace platform { namespace keys { const char* model = "model"; const char* clockSpeed = "clockSpeed"; const char* numCores = "numCores"; - } + const char* isMaster = "isMaster"; + } namespace gpu { const char* vendor = "vendor"; const char* vendor_NVIDIA = "NVIDIA"; @@ -31,14 +32,29 @@ namespace platform { namespace keys { const char* model = "model"; const char* videoMemory = "videoMemory"; const char* driver = "driver"; + const char* displays = "displays"; + const char* isMaster = "isMaster"; + } + namespace nic { + const char* mac = "mac"; + const char* name = "name"; } namespace display { const char* description = "description"; const char* name = "deviceName"; - const char* coordsLeft = "coordinatesleft"; - const char* coordsRight = "coordinatesright"; - const char* coordsTop = "coordinatestop"; - const char* coordsBottom = "coordinatesbottom"; + const char* boundsLeft = "boundsLeft"; + const char* boundsRight = "boundsRight"; + const char* boundsTop = "boundsTop"; + const char* boundsBottom = "boundsBottom"; + const char* gpu = "gpu"; + const char* ppi = "ppi"; + const char* ppiDesktop = "ppiDesktop"; + const char* physicalWidth = "physicalWidth"; + const char* physicalHeight = "physicalHeight"; + const char* modeRefreshrate = "modeRefreshrate"; + const char* modeWidth = "modeWidth"; + const char* modeHeight = "modeHeight"; + const char* isMaster = "isMaster"; } namespace memory { const char* memTotal = "memTotal"; @@ -63,6 +79,7 @@ namespace platform { namespace keys { const char* CPUS = "cpus"; const char* GPUS = "gpus"; const char* DISPLAYS = "displays"; + const char* NICS = "nics"; const char* MEMORY = "memory"; const char* COMPUTER = "computer"; }} @@ -112,6 +129,10 @@ json platform::getCPU(int index) { return _instance->getCPU(index); } +int platform::getMasterCPU() { + return _instance->getMasterCPU(); +} + int platform::getNumGPUs() { return _instance->getNumGPUs(); } @@ -120,6 +141,10 @@ json platform::getGPU(int index) { return _instance->getGPU(index); } +int platform::getMasterGPU() { + return _instance->getMasterGPU(); +} + int platform::getNumDisplays() { return _instance->getNumDisplays(); } @@ -128,6 +153,10 @@ json platform::getDisplay(int index) { return _instance->getDisplay(index); } +int platform::getMasterDisplay() { + return _instance->getMasterDisplay(); +} + json platform::getMemory() { return _instance->getMemory(); } diff --git a/libraries/platform/src/platform/backend/PlatformInstance.cpp b/libraries/platform/src/platform/backend/PlatformInstance.cpp index 41786bca1f..038521d398 100644 --- a/libraries/platform/src/platform/backend/PlatformInstance.cpp +++ b/libraries/platform/src/platform/backend/PlatformInstance.cpp @@ -8,6 +8,7 @@ #include "PlatformInstance.h" +#include #include "../PlatformKeys.h" #include "../Profiler.h" @@ -15,11 +16,23 @@ using namespace platform; bool Instance::enumeratePlatform() { + //clear all knowledge + _computer.clear(); + _memory.clear(); + _cpus.clear(); + _gpus.clear(); + _displays.clear(); + _nics.clear(); + + // enumerate platform components enumerateComputer(); enumerateMemory(); enumerateCpus(); - enumerateGpus(); - enumerateDisplays(); + enumerateGpusAndDisplays(); + enumerateNics(); + + // eval the master index for each platform scopes + updateMasterIndices(); // And profile the platform and put the tier in "computer" _computer[keys::computer::profileTier] = Profiler::TierNames[Profiler::profilePlatform()]; @@ -27,6 +40,71 @@ bool Instance::enumeratePlatform() { return true; } +void Instance::updateMasterIndices() { + // We assume a single CPU at the moment: + { + if (!_cpus.empty()) { + _masterCPU = 0; + _cpus[0][keys::cpu::isMaster] = true; + } else { + _masterCPU = NOT_FOUND; + } + } + + // Go through the displays list + { + _masterDisplay = NOT_FOUND; + for (int i = 0; i < (int) _displays.size(); ++i) { + const auto& display = _displays[i]; + if (display.count(keys::display::isMaster)) { + if (display[keys::display::isMaster].get()) { + _masterDisplay = i; + break; + } + } + } + // NO master display found, return the first one or NOT_FOUND if no display + if (_masterDisplay == NOT_FOUND) { + if (!_displays.empty()) { + _masterDisplay = 0; + _displays[0][keys::display::isMaster] = true; + } + } + } + + // From the master display decide the master gpu + { + _masterGPU = NOT_FOUND; + if (_masterDisplay != NOT_FOUND) { + const auto& display = _displays[_masterDisplay]; + // FInd the GPU index of the master display + if (display.count(keys::display::gpu)) { + _masterGPU = display[keys::display::gpu]; + _gpus[_masterGPU][keys::gpu::isMaster] = true; + } + } + // NO master GPU found from master display, bummer, return the first one or NOT_FOUND if no display + if (_masterGPU == NOT_FOUND) { + if (!_gpus.empty()) { + _masterGPU = 0; + _gpus[0][keys::gpu::isMaster] = true; + } + } + } +} + +void Instance::enumerateNics() { + QNetworkInterface interface; + foreach(interface, interface.allInterfaces()) { + if (interface.flags().testFlag(QNetworkInterface::IsRunning) && !interface.hardwareAddress().isEmpty()) { + json nic = {}; + nic[keys::nic::mac] = interface.hardwareAddress().toUtf8().constData(); + nic[keys::nic::name] = interface.humanReadableName().toUtf8().constData(); + _nics.push_back(nic); + } + } +} + json Instance::getCPU(int index) { assert(index <(int) _cpus.size()); if (index >= (int)_cpus.size()) @@ -44,6 +122,7 @@ json Instance::getGPU(int index) { return _gpus.at(index); } + json Instance::getDisplay(int index) { assert(index <(int) _displays.size()); @@ -85,13 +164,13 @@ json Instance::listAllKeys() { keys::gpu::model, keys::gpu::videoMemory, keys::gpu::driver, + keys::gpu::displays, - keys::display::description, - keys::display::name, - keys::display::coordsLeft, - keys::display::coordsRight, - keys::display::coordsTop, - keys::display::coordsBottom, + keys::display::boundsLeft, + keys::display::boundsRight, + keys::display::boundsTop, + keys::display::boundsBottom, + keys::display::gpu, keys::memory::memTotal, @@ -140,6 +219,7 @@ json Instance::getAll() { all[keys::CPUS] = _cpus; all[keys::GPUS] = _gpus; all[keys::DISPLAYS] = _displays; + all[keys::NICS] = _nics; return all; } diff --git a/libraries/platform/src/platform/backend/PlatformInstance.h b/libraries/platform/src/platform/backend/PlatformInstance.h index b7983446f5..069124853e 100644 --- a/libraries/platform/src/platform/backend/PlatformInstance.h +++ b/libraries/platform/src/platform/backend/PlatformInstance.h @@ -17,16 +17,21 @@ namespace platform { class Instance { public: + const int NOT_FOUND { -1 }; + bool virtual enumeratePlatform(); int getNumCPUs() { return (int)_cpus.size(); } json getCPU(int index); + int getMasterCPU() const { return _masterCPU; } int getNumGPUs() { return (int)_gpus.size(); } json getGPU(int index); + int getMasterGPU() const { return _masterGPU; } int getNumDisplays() { return (int)_displays.size(); } json getDisplay(int index); + int getMasterDisplay() const { return _masterDisplay; } json getMemory() { return _memory; } @@ -35,8 +40,8 @@ public: json getAll(); void virtual enumerateCpus()=0; - void virtual enumerateGpus()=0; - void virtual enumerateDisplays() {} + void virtual enumerateGpusAndDisplays()=0; + void virtual enumerateNics(); void virtual enumerateMemory() = 0; void virtual enumerateComputer()=0; @@ -51,8 +56,17 @@ protected: std::vector _cpus; std::vector _gpus; std::vector _displays; + std::vector _nics; json _memory; json _computer; + + int _masterCPU{ -1 }; + int _masterGPU{ -1 }; + int _masterDisplay{ -1 }; + + // Traverse the cpus, gpus and displays to update the "master" index in each domain + void updateMasterIndices(); + }; } // namespace platform diff --git a/libraries/platform/src/platform/backend/WINPlatform.cpp b/libraries/platform/src/platform/backend/WINPlatform.cpp index 9cf01ce4e0..e528618fe1 100644 --- a/libraries/platform/src/platform/backend/WINPlatform.cpp +++ b/libraries/platform/src/platform/backend/WINPlatform.cpp @@ -11,19 +11,31 @@ #include #include + #include -#include + +#include #ifdef Q_OS_WIN +#include +#include +#include #include +#include +#include #include +#include +#pragma comment(lib, "dxgi.lib") +#include +#pragma comment(lib, "Shcore.lib") + #endif using namespace platform; void WINInstance::enumerateCpus() { json cpu = {}; - + cpu[keys::cpu::vendor] = CPUIdent::Vendor(); cpu[keys::cpu::model] = CPUIdent::Brand(); cpu[keys::cpu::numCores] = std::thread::hardware_concurrency(); @@ -31,23 +43,153 @@ void WINInstance::enumerateCpus() { _cpus.push_back(cpu); } -void WINInstance::enumerateGpus() { +void WINInstance::enumerateGpusAndDisplays() { +#ifdef Q_OS_WIN + struct ConvertLargeIntegerToString { + std::string convert(const LARGE_INTEGER& version) { + std::ostringstream value; + value << uint32_t(((version.HighPart & 0xFFFF0000) >> 16) & 0x0000FFFF); + value << "."; + value << uint32_t((version.HighPart) & 0x0000FFFF); + value << "."; + value << uint32_t(((version.LowPart & 0xFFFF0000) >> 16) & 0x0000FFFF); + value << "."; + value << uint32_t((version.LowPart) & 0x0000FFFF); + + return value.str(); + } + } convertDriverVersionToString; - GPUIdent* ident = GPUIdent::getInstance(); - - json gpu = {}; - gpu[keys::gpu::model] = ident->getName().toUtf8().constData(); - gpu[keys::gpu::vendor] = findGPUVendorInDescription(gpu[keys::gpu::model].get()); - gpu[keys::gpu::videoMemory] = ident->getMemory(); - gpu[keys::gpu::driver] = ident->getDriver().toUtf8().constData(); + // Create the DXGI factory + // Let s get into DXGI land: + HRESULT hr = S_OK; - _gpus.push_back(gpu); - _displays = ident->getOutput(); + IDXGIFactory1* pFactory = nullptr; + hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)(&pFactory)); + if (hr != S_OK || pFactory == nullptr) { + return; + } + + std::vector validAdapterList; + using AdapterEntry = std::pair, std::vector>; + std::vector adapterToOutputs; + // Enumerate adapters and outputs + { + UINT adapterNum = 0; + IDXGIAdapter1* pAdapter = nullptr; + while (pFactory->EnumAdapters1(adapterNum, &pAdapter) != DXGI_ERROR_NOT_FOUND) { + // Found an adapter, get descriptor + DXGI_ADAPTER_DESC1 adapterDesc; + pAdapter->GetDesc1(&adapterDesc); + + // Only describe gpu if it is a hardware adapter + if (!(adapterDesc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)) { + + LARGE_INTEGER version; + hr = pAdapter->CheckInterfaceSupport(__uuidof(IDXGIDevice), &version); + + std::wstring wDescription(adapterDesc.Description); + std::string description(wDescription.begin(), wDescription.end()); + + json gpu = {}; + gpu[keys::gpu::model] = description; + gpu[keys::gpu::vendor] = findGPUVendorInDescription(gpu[keys::gpu::model].get()); + const SIZE_T BYTES_PER_MEGABYTE = 1024 * 1024; + gpu[keys::gpu::videoMemory] = (uint32_t)(adapterDesc.DedicatedVideoMemory / BYTES_PER_MEGABYTE); + gpu[keys::gpu::driver] = convertDriverVersionToString.convert(version); + + std::vector displayIndices; + + UINT outputNum = 0; + IDXGIOutput* pOutput; + bool hasOutputConnectedToDesktop = false; + while (pAdapter->EnumOutputs(outputNum, &pOutput) != DXGI_ERROR_NOT_FOUND) { + // FOund an output attached to the adapter, get descriptor + DXGI_OUTPUT_DESC outputDesc; + pOutput->GetDesc(&outputDesc); + pOutput->Release(); + outputNum++; + + // Grab the monitor info + MONITORINFO monitorInfo; + monitorInfo.cbSize = sizeof(MONITORINFO); + GetMonitorInfo(outputDesc.Monitor, &monitorInfo); + + // Grab the dpi info for the monitor + UINT dpiX{ 0 }; + UINT dpiY{ 0 }; + GetDpiForMonitor(outputDesc.Monitor, MDT_RAW_DPI, &dpiX, &dpiY); + UINT dpiXScaled{ 0 }; + UINT dpiYScaled{ 0 }; + GetDpiForMonitor(outputDesc.Monitor, MDT_EFFECTIVE_DPI, &dpiXScaled, &dpiYScaled); + + // Current display mode + DEVMODEW devMode; + devMode.dmSize = sizeof(DEVMODEW); + EnumDisplaySettingsW(outputDesc.DeviceName, ENUM_CURRENT_SETTINGS, &devMode); + + auto physicalWidth = devMode.dmPelsWidth / (float)dpiX; + auto physicalHeight = devMode.dmPelsHeight / (float)dpiY; + + json display = {}; + + // Display name + std::wstring wDeviceName(outputDesc.DeviceName); + std::string deviceName(wDeviceName.begin(), wDeviceName.end()); + display[keys::display::name] = deviceName; + display[keys::display::description] = ""; + + // Rect region of the desktop in desktop units + //display["desktopRect"] = (outputDesc.AttachedToDesktop ? true : false); + display[keys::display::boundsLeft] = outputDesc.DesktopCoordinates.left; + display[keys::display::boundsRight] = outputDesc.DesktopCoordinates.right; + display[keys::display::boundsBottom] = outputDesc.DesktopCoordinates.bottom; + display[keys::display::boundsTop] = outputDesc.DesktopCoordinates.top; + + // PPI & resolution + display[keys::display::physicalWidth] = physicalWidth; + display[keys::display::physicalHeight] = physicalHeight; + display[keys::display::modeWidth] = devMode.dmPelsWidth; + display[keys::display::modeHeight] = devMode.dmPelsHeight; + + //Average the ppiH and V for the simple ppi + display[keys::display::ppi] = std::round(0.5f * (dpiX + dpiY)); + display[keys::display::ppiDesktop] = std::round(0.5f * (dpiXScaled + dpiYScaled)); + + // refreshrate + display[keys::display::modeRefreshrate] = devMode.dmDisplayFrequency;; + + // Master display ? + display[keys::display::isMaster] = (bool) (monitorInfo.dwFlags & MONITORINFOF_PRIMARY); + + // Add the display index to the list of displays of the gpu + displayIndices.push_back((int) _displays.size()); + + // And set the gpu index to the display description + display[keys::display::gpu] = (int) _gpus.size(); + + // WIN specific + + + // One more display desc + _displays.push_back(display); + } + gpu[keys::gpu::displays] = displayIndices; + + _gpus.push_back(gpu); + } + + pAdapter->Release(); + adapterNum++; + } + } + pFactory->Release(); +#endif } void WINInstance::enumerateMemory() { json ram = {}; - + #ifdef Q_OS_WIN MEMORYSTATUSEX statex; statex.dwLength = sizeof(statex); @@ -58,13 +200,54 @@ void WINInstance::enumerateMemory() { _memory = ram; } -void WINInstance::enumerateComputer(){ +void WINInstance::enumerateComputer() { _computer[keys::computer::OS] = keys::computer::OS_WINDOWS; _computer[keys::computer::vendor] = ""; _computer[keys::computer::model] = ""; - - auto sysInfo = QSysInfo(); +#ifdef Q_OS_WIN + auto sysInfo = QSysInfo(); _computer[keys::computer::OSVersion] = sysInfo.kernelVersion().toStdString(); +#endif } + +void WINInstance::enumerateNics() { + // Start with the default from QT, getting the result into _nics: + Instance::enumerateNics(); + +#ifdef Q_OS_WIN + // We can usually do better than the QNetworkInterface::humanReadableName() by + // matching up Iphlpapi.lib IP_ADAPTER_INFO by mac id. + ULONG buflen = sizeof(IP_ADAPTER_INFO); + IP_ADAPTER_INFO* pAdapterInfo = (IP_ADAPTER_INFO*)malloc(buflen); + + // Size the buffer: + if (GetAdaptersInfo(pAdapterInfo, &buflen) == ERROR_BUFFER_OVERFLOW) { + free(pAdapterInfo); + pAdapterInfo = (IP_ADAPTER_INFO*)malloc(buflen); + } + + // Now get the data... + if (GetAdaptersInfo(pAdapterInfo, &buflen) == NO_ERROR) { + for (json& nic : _nics) { // ... loop through the nics from above... + // ...convert the json to a string without the colons... + QString qtmac = nic[keys::nic::mac].get().c_str(); + QString qtraw = qtmac.remove(QChar(':'), Qt::CaseInsensitive).toLower(); + // ... and find the matching one in pAdapter: + for (IP_ADAPTER_INFO* pAdapter = pAdapterInfo; pAdapter; pAdapter = pAdapter->Next) { + QByteArray wmac = QByteArray((const char*)(pAdapter->Address), pAdapter->AddressLength); + QString wraw = wmac.toHex(); + if (qtraw == wraw) { + nic[keys::nic::name] = pAdapter->Description; + break; + } + } + } + } + + if (pAdapterInfo) { + free(pAdapterInfo); + } +#endif +} diff --git a/libraries/platform/src/platform/backend/WINPlatform.h b/libraries/platform/src/platform/backend/WINPlatform.h index cb6d3f482f..cc56ebfbbc 100644 --- a/libraries/platform/src/platform/backend/WINPlatform.h +++ b/libraries/platform/src/platform/backend/WINPlatform.h @@ -16,9 +16,10 @@ namespace platform { public: void enumerateCpus() override; - void enumerateGpus() override; + void enumerateGpusAndDisplays() override; void enumerateMemory() override; void enumerateComputer () override; + void enumerateNics() override; }; } // namespace platform diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index ca4e3bc392..2315f6e4ba 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -210,7 +210,7 @@ public: // for updating plugin-related commands. Mimics the input plugin. virtual void pluginUpdate() = 0; - virtual std::function getHUDOperator() { return nullptr; } + virtual std::function getHUDOperator() { return nullptr; } virtual StencilMaskMode getStencilMaskMode() const { return StencilMaskMode::NONE; } using StencilMaskMeshOperator = std::function; virtual StencilMaskMeshOperator getStencilMaskMeshOperator() { return nullptr; } diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index 735b1a48f6..db0f2ca6c9 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -442,11 +442,11 @@ glm::vec4 Procedural::getColor(const glm::vec4& entityColor) const { } void graphics::ProceduralMaterial::initializeProcedural() { - _procedural._vertexSource = gpu::Shader::getVertexShaderSource(shader::render_utils::vertex::simple); - _procedural._vertexSourceSkinned = gpu::Shader::getVertexShaderSource(shader::render_utils::vertex::deformed_simple); - _procedural._vertexSourceSkinnedDQ = gpu::Shader::getVertexShaderSource(shader::render_utils::vertex::deformed_simple_dq); + _procedural._vertexSource = gpu::Shader::getVertexShaderSource(shader::render_utils::vertex::simple_procedural); + _procedural._vertexSourceSkinned = gpu::Shader::getVertexShaderSource(shader::render_utils::vertex::simple_procedural_deformed); + _procedural._vertexSourceSkinnedDQ = gpu::Shader::getVertexShaderSource(shader::render_utils::vertex::simple_procedural_deformeddq); // FIXME: Setup proper uniform slots and use correct pipelines for forward rendering - _procedural._opaqueFragmentSource = gpu::Shader::getFragmentShaderSource(shader::render_utils::fragment::simple); - _procedural._transparentFragmentSource = gpu::Shader::getFragmentShaderSource(shader::render_utils::fragment::simple_transparent); + _procedural._opaqueFragmentSource = gpu::Shader::getFragmentShaderSource(shader::render_utils::fragment::simple_procedural); + _procedural._transparentFragmentSource = gpu::Shader::getFragmentShaderSource(shader::render_utils::fragment::simple_procedural_translucent); } \ No newline at end of file diff --git a/libraries/procedural/src/procedural/ProceduralMaterialCache.cpp b/libraries/procedural/src/procedural/ProceduralMaterialCache.cpp index 83cba9d781..39861052c5 100644 --- a/libraries/procedural/src/procedural/ProceduralMaterialCache.cpp +++ b/libraries/procedural/src/procedural/ProceduralMaterialCache.cpp @@ -117,16 +117,18 @@ NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMater * Supported models are: "hifi_pbr", "hifi_shader_simple". * @property {string} name="" - A name for the material. Supported by all material models. * @property {ColorFloat|RGBS|string} emissive - The emissive color, i.e., the color that the material emits. A - * {@link ColorFloat} value is treated as sRGB and must have component values in the range 0.0 — + * {@link ColorFloat} value is treated as sRGB and must have component values in the range 0.0 – * 1.0. A {@link RGBS} value can be either RGB or sRGB. * Set to "fallthrough" to fall through to the material below. "hifi_pbr" model only. - * @property {number|string} opacity=1.0 - The opacity, range 0.01.0. + * @property {number|string} opacity=1.0 - The opacity, range 0.01.0. + * Set to "fallthrough" to fall through to the material below. "hifi_pbr" and + * "hifi_shader_simple" models only. + * @property {boolean|string} unlit=false - true if the material is not lit, false if it is. * Set to "fallthrough" to fall through to the material below. "hifi_pbr" model only. - * @property {boolean|string} unlit=false - If true, the material is not lit, otherwise it is. - * Set to "fallthrough" to fall through to the material below. Supported by all material models. - * @property {ColorFloat|RGBS|string} albedo - The albedo color. A {@link ColorFloat} value is treated as sRGB and must have - * component values in the range 0.01.0. A {@link RGBS} value can be either RGB or sRGB. - * Set to "fallthrough" to fall through to the material below. Supported by all material models. + * @property {ColorFloat|RGBS|string} albedo - The albedo color. A {@link ColorFloat} value is treated as sRGB and must have + * component values in the range 0.01.0. A {@link RGBS} value can be either RGB or sRGB. + * Set to "fallthrough" to fall through to the material below. "hifi_pbr" and + * "hifi_shader_simple" models only. * @property {number|string} roughness - The roughness, range 0.01.0. * Set to "fallthrough" to fall through to the material below. "hifi_pbr" model only. * @property {number|string} metallic - The metallicness, range 0.01.0. @@ -174,9 +176,9 @@ NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMater * @property {string} materialParams - Parameters for controlling the material projection and repetition. * Set to "fallthrough" to fall through to the material below. "hifi_pbr" model only. *

Currently not used.

- * @property {boolean} defaultFallthrough=false - If true, all properties fall through to the material below - * unless they are set. If false, they respect their individual fall-through setting. "hifi_pbr" - * model only. + * @property {boolean} defaultFallthrough=false - true if all properties fall through to the material below + * unless they are set, false if properties respect their individual fall-through settings. + * "hifi_pbr" model only. * @property {ProceduralData} procedural - The definition of a procedural shader material. "hifi_shader_simple" model only. */ // Note: See MaterialEntityItem.h for default values used in practice. @@ -478,11 +480,6 @@ std::pair> NetworkMaterialResource return std::pair>(name, networkMaterial); } -MaterialCache& MaterialCache::instance() { - static MaterialCache _instance; - return _instance; -} - NetworkMaterialResourcePointer MaterialCache::getMaterial(const QUrl& url) { return ResourceCache::getResource(url).staticCast(); } @@ -798,4 +795,4 @@ void NetworkMaterial::checkResetOpacityMap() { if (albedoTexture.texture) { resetOpacityMap(); } -} \ No newline at end of file +} diff --git a/libraries/procedural/src/procedural/ProceduralMaterialCache.h b/libraries/procedural/src/procedural/ProceduralMaterialCache.h index a614138ff9..baa8daeb49 100644 --- a/libraries/procedural/src/procedural/ProceduralMaterialCache.h +++ b/libraries/procedural/src/procedural/ProceduralMaterialCache.h @@ -110,10 +110,11 @@ using NetworkMaterialResourcePointer = QSharedPointer; using MaterialMapping = std::vector>; Q_DECLARE_METATYPE(MaterialMapping) -class MaterialCache : public ResourceCache { -public: - static MaterialCache& instance(); +class MaterialCache : public ResourceCache, public Dependency { + Q_OBJECT + SINGLETON_DEPENDENCY +public: NetworkMaterialResourcePointer getMaterial(const QUrl& url); protected: diff --git a/libraries/procedural/src/procedural/ProceduralSkybox.cpp b/libraries/procedural/src/procedural/ProceduralSkybox.cpp index d852d9242c..432e02fe10 100644 --- a/libraries/procedural/src/procedural/ProceduralSkybox.cpp +++ b/libraries/procedural/src/procedural/ProceduralSkybox.cpp @@ -18,8 +18,10 @@ #include ProceduralSkybox::ProceduralSkybox(uint64_t created) : graphics::Skybox(), _created(created) { - _procedural._vertexSource = gpu::Shader::Source::get(shader::graphics::vertex::skybox); - _procedural._opaqueFragmentSource = gpu::Shader::Source::get(shader::procedural::fragment::proceduralSkybox); + // FIXME: support forward rendering for procedural skyboxes (needs haze calculation) + _procedural._vertexSource = shader::Source::get(shader::graphics::vertex::skybox); + _procedural._opaqueFragmentSource = shader::Source::get(shader::procedural::fragment::proceduralSkybox); + _procedural.setDoesFade(false); // Adjust the pipeline state for background using the stencil test @@ -41,15 +43,15 @@ void ProceduralSkybox::clear() { Skybox::clear(); } -void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& frustum) const { +void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& frustum, bool forward) const { if (_procedural.isReady()) { - ProceduralSkybox::render(batch, frustum, (*this)); + ProceduralSkybox::render(batch, frustum, (*this), forward); } else { - Skybox::render(batch, frustum); + Skybox::render(batch, frustum, forward); } } -void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const ProceduralSkybox& skybox) { +void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const ProceduralSkybox& skybox, bool forward) { glm::mat4 projMat; viewFrustum.evalProjectionMatrix(projMat); diff --git a/libraries/procedural/src/procedural/ProceduralSkybox.h b/libraries/procedural/src/procedural/ProceduralSkybox.h index a1d7ea8fa7..983b432089 100644 --- a/libraries/procedural/src/procedural/ProceduralSkybox.h +++ b/libraries/procedural/src/procedural/ProceduralSkybox.h @@ -26,8 +26,8 @@ public: bool empty() override; void clear() override; - void render(gpu::Batch& batch, const ViewFrustum& frustum) const override; - static void render(gpu::Batch& batch, const ViewFrustum& frustum, const ProceduralSkybox& skybox); + void render(gpu::Batch& batch, const ViewFrustum& frustum, bool forward) const override; + static void render(gpu::Batch& batch, const ViewFrustum& frustum, const ProceduralSkybox& skybox, bool forward); uint64_t getCreated() const { return _created; } diff --git a/libraries/qml/src/qml/OffscreenSurface.cpp b/libraries/qml/src/qml/OffscreenSurface.cpp index 69e6c833ee..117ff61c6e 100644 --- a/libraries/qml/src/qml/OffscreenSurface.cpp +++ b/libraries/qml/src/qml/OffscreenSurface.cpp @@ -23,6 +23,7 @@ #include #include +#include #include "Logging.h" #include "impl/SharedObject.h" @@ -33,6 +34,23 @@ using namespace hifi::qml; using namespace hifi::qml::impl; +QmlUrlValidator OffscreenSurface::validator = [](const QUrl& url) -> bool { + if (url.isRelative()) { + return true; + } + + if (url.isLocalFile()) { + return true; + } + + if (url.scheme() == URL_SCHEME_QRC) { + return true; + } + + // By default, only allow local QML, either from the local filesystem or baked into the QRC + return false; +}; + static uvec2 clampSize(const uvec2& size, uint32_t maxDimension) { return glm::clamp(size, glm::uvec2(1), glm::uvec2(maxDimension)); } @@ -307,6 +325,10 @@ void OffscreenSurface::loadInternal(const QUrl& qmlSource, // For desktop toolbar mode window: stop script when window is closed. if (qmlSource.isEmpty()) { getSurfaceContext()->engine()->quit(); + } + + if (!validator(qmlSource)) { + qCWarning(qmlLogging) << "Unauthorized QML URL found" << qmlSource; return; } diff --git a/libraries/qml/src/qml/OffscreenSurface.h b/libraries/qml/src/qml/OffscreenSurface.h index 18d24c93f7..528baf76be 100644 --- a/libraries/qml/src/qml/OffscreenSurface.h +++ b/libraries/qml/src/qml/OffscreenSurface.h @@ -40,6 +40,7 @@ class SharedObject; using QmlContextCallback = ::std::function; using QmlContextObjectCallback = ::std::function; +using QmlUrlValidator = std::function; class OffscreenSurface : public QObject { Q_OBJECT @@ -47,10 +48,13 @@ class OffscreenSurface : public QObject { public: static const QmlContextObjectCallback DEFAULT_CONTEXT_OBJECT_CALLBACK; static const QmlContextCallback DEFAULT_CONTEXT_CALLBACK; - + static QmlUrlValidator validator; using TextureAndFence = std::pair; using MouseTranslator = std::function; + + static const QmlUrlValidator& getUrlValidator() { return validator; } + static void setUrlValidator(const QmlUrlValidator& newValidator) { validator = newValidator; } static void setSharedContext(QOpenGLContext* context); OffscreenSurface(); diff --git a/libraries/render-utils/src/BackgroundStage.cpp b/libraries/render-utils/src/BackgroundStage.cpp index ca643b9f14..91b766d90b 100644 --- a/libraries/render-utils/src/BackgroundStage.cpp +++ b/libraries/render-utils/src/BackgroundStage.cpp @@ -13,6 +13,8 @@ #include +#include + std::string BackgroundStage::_stageName { "BACKGROUND_STAGE"}; const BackgroundStage::Index BackgroundStage::INVALID_INDEX { render::indexed_container::INVALID_INDEX }; @@ -71,6 +73,8 @@ void DrawBackgroundStage::run(const render::RenderContextPointer& renderContext, } } + const auto& hazeFrame = inputs.get2(); + if (skybox && !skybox->empty()) { PerformanceTimer perfTimer("skybox"); auto args = renderContext->args; @@ -91,7 +95,18 @@ void DrawBackgroundStage::run(const render::RenderContextPointer& renderContext, batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); - skybox->render(batch, args->getViewFrustum()); + // If we're using forward rendering, we need to calculate haze + if (args->_renderMethod == render::Args::RenderMethod::FORWARD) { + const auto& hazeStage = args->_scene->getStage(); + if (hazeStage && hazeFrame->_hazes.size() > 0) { + const auto& hazePointer = hazeStage->getHaze(hazeFrame->_hazes.front()); + if (hazePointer) { + batch.setUniformBuffer(graphics::slot::buffer::Buffer::HazeParams, hazePointer->getHazeParametersBuffer()); + } + } + } + + skybox->render(batch, args->getViewFrustum(), args->_renderMethod == render::Args::RenderMethod::FORWARD); }); args->_batch = nullptr; } diff --git a/libraries/render-utils/src/BackgroundStage.h b/libraries/render-utils/src/BackgroundStage.h index 61ca576ca8..3015b721b1 100644 --- a/libraries/render-utils/src/BackgroundStage.h +++ b/libraries/render-utils/src/BackgroundStage.h @@ -16,6 +16,7 @@ #include #include #include +#include "HazeStage.h" #include "LightingModel.h" @@ -81,7 +82,7 @@ public: class DrawBackgroundStage { public: - using Inputs = render::VaryingSet2; + using Inputs = render::VaryingSet3; using JobModel = render::Job::ModelI; DrawBackgroundStage() {} diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 3ab9340906..3b7c66d42d 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -432,7 +432,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, if (hazeStage && hazeFrame->_hazes.size() > 0) { const auto& hazePointer = hazeStage->getHaze(hazeFrame->_hazes.front()); if (hazePointer) { - batch.setUniformBuffer(ru::Buffer::HazeParams, hazePointer->getHazeParametersBuffer()); + batch.setUniformBuffer(graphics::slot::buffer::Buffer::HazeParams, hazePointer->getHazeParametersBuffer()); } } @@ -655,7 +655,6 @@ void DefaultLightingSetup::run(const RenderContextPointer& renderContext) { if (!_defaultHaze) { auto hazeStage = renderContext->_scene->getStage(); if (hazeStage) { - auto haze = std::make_shared(); _defaultHaze = haze; diff --git a/libraries/render-utils/src/DrawHaze.cpp b/libraries/render-utils/src/DrawHaze.cpp index db80cbecae..f7be5160b6 100644 --- a/libraries/render-utils/src/DrawHaze.cpp +++ b/libraries/render-utils/src/DrawHaze.cpp @@ -78,7 +78,7 @@ void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inpu batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(outputFramebufferSize, args->_viewport)); batch.setPipeline(_hazePipeline); - batch.setUniformBuffer(ru::Buffer::HazeParams, haze->getHazeParametersBuffer()); + batch.setUniformBuffer(graphics::slot::buffer::Buffer::HazeParams, haze->getHazeParametersBuffer()); batch.setUniformBuffer(ru::Buffer::DeferredFrameTransform, transformBuffer->getFrameTransformBuffer()); batch.setUniformBuffer(ru::Buffer::LightModel, lightingModel->getParametersBuffer()); diff --git a/libraries/render-utils/src/ForwardGlobalLight.slh b/libraries/render-utils/src/ForwardGlobalLight.slh deleted file mode 100644 index cf5f070c55..0000000000 --- a/libraries/render-utils/src/ForwardGlobalLight.slh +++ /dev/null @@ -1,247 +0,0 @@ - -<@if not DEFERRED_GLOBAL_LIGHT_SLH@> -<@def DEFERRED_GLOBAL_LIGHT_SLH@> - -<@include graphics/Light.slh@> - -<@include LightingModel.slh@> -<$declareLightBuffer()$> -<$declareLightAmbientBuffer()$> - -<@include LightAmbient.slh@> -<@include LightDirectional.slh@> - -<@func prepareGlobalLight(positionES, normalWS)@> - // prepareGlobalLight - // Transform directions to worldspace - vec3 fragNormalWS = vec3(<$normalWS$>); - vec3 fragPositionWS = vec3(invViewMat * vec4(<$positionES$>, 1.0)); - vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS; - vec3 fragEyeDirWS = normalize(fragEyeVectorWS); - - // Get light - Light light = getKeyLight(); - LightAmbient lightAmbient = getLightAmbient(); - - vec3 lightDirection = getLightDirection(light); - vec3 lightIrradiance = getLightIrradiance(light); - - vec3 color = vec3(0.0); - -<@endfunc@> - - -<@func declareEvalAmbientGlobalColor()@> -vec3 evalAmbientGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, float roughness) { - <$prepareGlobalLight(position, normal)$> - color += albedo * getLightColor(light) * obscurance * getLightAmbientIntensity(lightAmbient); - return color; -} -<@endfunc@> - -<@func declareEvalAmbientSphereGlobalColor(supportScattering)@> - -<$declareLightingAmbient(1, _SCRIBE_NULL, _SCRIBE_NULL, $supportScattering$)$> -<$declareLightingDirectional($supportScattering$)$> - -<@if supportScattering@> -<$declareDeferredCurvature()$> -<@endif@> - -vec3 evalAmbientSphereGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, -vec3 albedo, vec3 fresnel, float metallic, float roughness -<@if supportScattering@> - , float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature -<@endif@> ) { - - <$prepareGlobalLight(position, normal)$> - - SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS); - - // Ambient - vec3 ambientDiffuse; - vec3 ambientSpecular; - evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance -<@if supportScattering@> - ,scattering, midNormalCurvature, lowNormalCurvature -<@endif@> ); - color += ambientDiffuse; - color += ambientSpecular; - - - // Directional - vec3 directionalDiffuse; - vec3 directionalSpecular; - evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation -<@if supportScattering@> - ,scattering, midNormalCurvature, lowNormalCurvature -<@endif@> ); - color += directionalDiffuse; - color += directionalSpecular; - - return color; -} - -<@endfunc@> - - -<@func declareEvalSkyboxGlobalColor(supportScattering)@> - -<$declareLightingAmbient(_SCRIBE_NULL, 1, _SCRIBE_NULL, $supportScattering$)$> -<$declareLightingDirectional($supportScattering$)$> - -<@if supportScattering@> -<$declareDeferredCurvature()$> -<@endif@> - -vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, - vec3 albedo, vec3 fresnel, float metallic, float roughness -<@if supportScattering@> - , float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature -<@endif@> - ) { - <$prepareGlobalLight(position, normal)$> - - SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS); - - // Ambient - vec3 ambientDiffuse; - vec3 ambientSpecular; - evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance -<@if supportScattering@> - ,scattering, midNormalCurvature, lowNormalCurvature -<@endif@> - ); - color += ambientDiffuse; - color += ambientSpecular; - - vec3 directionalDiffuse; - vec3 directionalSpecular; - evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation -<@if supportScattering@> - ,scattering, midNormalCurvature, lowNormalCurvature -<@endif@> - ); - color += directionalDiffuse; - color += directionalSpecular; - - // FIXME - temporarily removed until we support it for forward... - // Attenuate the light if haze effect selected - // if ((hazeParams.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) { - // color = computeHazeColorKeyLightAttenuation(color, lightDirection, fragPositionWS); - // } - - return color; -} - -<@endfunc@> - -<@func declareEvalLightmappedColor()@> -vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 normal, vec3 albedo, vec3 lightmap) { - Light light = getKeyLight(); - LightAmbient ambient = getLightAmbient(); - - // Catch normals perpendicular to the projection plane, hence the magic number for the threshold - // It should be just 0, but we have inaccuracy so we overshoot - const float PERPENDICULAR_THRESHOLD = -0.005; - vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); // transform to worldspace - float diffuseDot = dot(fragNormal, -getLightDirection(light)); - float facingLight = step(PERPENDICULAR_THRESHOLD, diffuseDot); - - // Reevaluate the shadow attenuation for light facing fragments - float lightAttenuation = (1.0 - facingLight) + facingLight * shadowAttenuation; - - // Diffuse light is the lightmap dimmed by shadow - vec3 diffuseLight = lightAttenuation * lightmap; - - // Ambient light is the lightmap when in shadow - vec3 ambientLight = (1.0 - lightAttenuation) * lightmap * getLightAmbientIntensity(ambient); - - return isLightmapEnabled() * obscurance * albedo * (diffuseLight + ambientLight); -} -<@endfunc@> - - - -<@include Haze.slh@> - -<@func declareEvalGlobalLightingAlphaBlended()@> - -<$declareLightingAmbient(1, 1, 1)$> -<$declareLightingDirectional()$> - -vec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) { - <$prepareGlobalLight(position, normal)$> - - SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS); - - color += emissive * isEmissiveEnabled(); - - // Ambient - vec3 ambientDiffuse; - vec3 ambientSpecular; - evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance); - color += ambientDiffuse; - - // Directional - vec3 directionalDiffuse; - vec3 directionalSpecular; - evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation); - color += directionalDiffuse; - color += evalSpecularWithOpacity(ambientSpecular + directionalSpecular, opacity); - - return color; -} - -vec3 evalGlobalLightingAlphaBlendedWithHaze( - mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, - vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) -{ - <$prepareGlobalLight(position, normal)$> - - SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS); - - color += emissive * isEmissiveEnabled(); - - // Ambient - vec3 ambientDiffuse; - vec3 ambientSpecular; - evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance); - color += ambientDiffuse; - - // Directional - vec3 directionalDiffuse; - vec3 directionalSpecular; - evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation); - color += directionalDiffuse; - color += evalSpecularWithOpacity(ambientSpecular + directionalSpecular, opacity); - - // Haze - // FIXME - temporarily removed until we support it for forward... - /* if ((hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) { - vec4 hazeColor = computeHazeColor( - positionES, // fragment position in eye coordinates - fragPositionWS, // fragment position in world coordinates - invViewMat[3].xyz, // eye position in world coordinates - lightDirection // keylight direction vector - ); - - color = mix(color.rgb, hazeColor.rgb, hazeColor.a); - }*/ - - return color; -} - -<@endfunc@> - - -<@endif@> diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 88cca1693b..997f87b8d6 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -113,6 +113,7 @@ static const uint SHAPE_NORMALS_OFFSET = offsetof(GeometryCache::ShapeVertex, no static const uint SHAPE_TEXCOORD0_OFFSET = offsetof(GeometryCache::ShapeVertex, uv); static const uint SHAPE_TANGENT_OFFSET = offsetof(GeometryCache::ShapeVertex, tangent); +std::map, gpu::PipelinePointer> GeometryCache::_webPipelines; std::map, gpu::PipelinePointer> GeometryCache::_gridPipelines; void GeometryCache::computeSimpleHullPointListForShape(const int entityShape, const glm::vec3 &entityExtents, QVector &outPointList) { @@ -722,42 +723,12 @@ gpu::ShaderPointer GeometryCache::_forwardUnlitShader; gpu::ShaderPointer GeometryCache::_forwardSimpleFadeShader; gpu::ShaderPointer GeometryCache::_forwardUnlitFadeShader; -render::ShapePipelinePointer GeometryCache::_simpleOpaquePipeline; -render::ShapePipelinePointer GeometryCache::_simpleTransparentPipeline; -render::ShapePipelinePointer GeometryCache::_forwardSimpleOpaquePipeline; -render::ShapePipelinePointer GeometryCache::_forwardSimpleTransparentPipeline; -render::ShapePipelinePointer GeometryCache::_simpleOpaqueFadePipeline; -render::ShapePipelinePointer GeometryCache::_simpleTransparentFadePipeline; -render::ShapePipelinePointer GeometryCache::_simpleWirePipeline; - -uint8_t GeometryCache::CUSTOM_PIPELINE_NUMBER = 0; - -render::ShapePipelinePointer GeometryCache::shapePipelineFactory(const render::ShapePlumber& plumber, const render::ShapeKey& key, gpu::Batch& batch) { - initializeShapePipelines(); - - if (key.isWireframe()) { - return _simpleWirePipeline; - } - - if (key.isFaded()) { - if (key.isTranslucent()) { - return _simpleTransparentFadePipeline; - } else { - return _simpleOpaqueFadePipeline; - } - } else { - if (key.isTranslucent()) { - return _simpleTransparentPipeline; - } else { - return _simpleOpaquePipeline; - } - } -} +std::map, render::ShapePipelinePointer> GeometryCache::_shapePipelines; GeometryCache::GeometryCache() : _nextID(0) { // Let's register its special shapePipeline factory: - registerShapePipeline(); + initializeShapePipelines(); buildShapes(); } @@ -799,16 +770,14 @@ void GeometryCache::releaseID(int id) { } void GeometryCache::initializeShapePipelines() { - if (!_simpleOpaquePipeline) { - _simpleOpaquePipeline = getShapePipeline(false, false, true, false); - _simpleTransparentPipeline = getShapePipeline(false, true, true, false); - _forwardSimpleOpaquePipeline = getShapePipeline(false, false, true, false, false, true); - _forwardSimpleTransparentPipeline = getShapePipeline(false, true, true, false, false, true); - - // FIXME: these need forward pipelines - _simpleOpaqueFadePipeline = getFadingShapePipeline(false, false, false, false, false); - _simpleTransparentFadePipeline = getFadingShapePipeline(false, true, false, false, false); - _simpleWirePipeline = getShapePipeline(false, false, true, true); + if (_shapePipelines.empty()) { + const int NUM_PIPELINES = 8; + for (int i = 0; i < NUM_PIPELINES; ++i) { + bool transparent = i & 1; + bool unlit = i & 2; + bool forward = i & 4; + _shapePipelines[std::make_tuple(transparent, unlit, forward)] = getShapePipeline(false, transparent, true, unlit, false, forward); + } } } @@ -1027,7 +996,7 @@ void GeometryCache::updateVertices(int id, const QVector& points, con int* colorData = new int[details.vertices]; int* colorDataAt = colorData; - const glm::vec3 NORMAL(0.0f, 1.0f, 0.0f); + const glm::vec3 NORMAL(0.0f, -1.0f, 0.0f); auto pointCount = points.size(); auto colorCount = colors.size(); int compactColor = 0; @@ -1105,7 +1074,7 @@ void GeometryCache::updateVertices(int id, const QVector& points, con int* colorData = new int[details.vertices]; int* colorDataAt = colorData; - const glm::vec3 NORMAL(0.0f, 1.0f, 0.0f); + const glm::vec3 NORMAL(0.0f, -1.0f, 0.0f); auto pointCount = points.size(); auto colorCount = colors.size(); for (auto i = 0; i < pointCount; i++) { @@ -1193,7 +1162,7 @@ void GeometryCache::updateVertices(int id, const QVector& points, con int* colorData = new int[details.vertices]; int* colorDataAt = colorData; - const glm::vec3 NORMAL(0.0f, 1.0f, 0.0f); + const glm::vec3 NORMAL(0.0f, -1.0f, 0.0f); for (int i = 0; i < points.size(); i++) { glm::vec3 point = points[i]; glm::vec2 texCoord = texCoords[i]; @@ -2050,7 +2019,7 @@ void GeometryCache::useGridPipeline(gpu::Batch& batch, GridBuffer gridBuffer, bo const float DEPTH_BIAS = 0.001f; static const std::vector> keys = { - std::make_tuple(false, false, grid), std::make_tuple(false, true, forward_grid), std::make_tuple(true, false, grid_translucent), std::make_tuple(true, true, forward_grid_translucent) + std::make_tuple(false, false, grid), std::make_tuple(false, true, grid_forward), std::make_tuple(true, false, grid_translucent), std::make_tuple(true, true, grid_translucent_forward) }; for (auto& key : keys) { @@ -2141,34 +2110,35 @@ inline bool operator==(const SimpleProgramKey& a, const SimpleProgramKey& b) { return a.getRaw() == b.getRaw(); } -static void buildWebShader(int programId, bool blendEnable, - gpu::ShaderPointer& shaderPointerOut, gpu::PipelinePointer& pipelinePointerOut) { - shaderPointerOut = gpu::Shader::createProgram(programId); - auto state = std::make_shared(); - state->setCullMode(gpu::State::CULL_NONE); - state->setDepthTest(true, true, gpu::LESS_EQUAL); - state->setBlendFunction(blendEnable, - gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, - gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); - - PrepareStencil::testMaskDrawShapeNoAA(*state); - - pipelinePointerOut = gpu::Pipeline::create(shaderPointerOut, state); +void GeometryCache::bindWebBrowserProgram(gpu::Batch& batch, bool transparent, bool forward) { + batch.setPipeline(getWebBrowserProgram(transparent, forward)); } -void GeometryCache::bindWebBrowserProgram(gpu::Batch& batch, bool transparent) { - batch.setPipeline(getWebBrowserProgram(transparent)); -} +gpu::PipelinePointer GeometryCache::getWebBrowserProgram(bool transparent, bool forward) { + if (_webPipelines.empty()) { + using namespace shader::render_utils::program; + const int NUM_WEB_PIPELINES = 4; + for (int i = 0; i < NUM_WEB_PIPELINES; ++i) { + bool transparent = i & 1; + bool forward = i & 2; -gpu::PipelinePointer GeometryCache::getWebBrowserProgram(bool transparent) { - static std::once_flag once; - std::call_once(once, [&]() { - // FIXME: need a forward pipeline for this - buildWebShader(shader::render_utils::program::simple_opaque_web_browser, false, _simpleOpaqueWebBrowserShader, _simpleOpaqueWebBrowserPipeline); - buildWebShader(shader::render_utils::program::simple_transparent_web_browser, true, _simpleTransparentWebBrowserShader, _simpleTransparentWebBrowserPipeline); - }); + // For any non-opaque or non-deferred pipeline, we use web_browser_forward + auto pipeline = (transparent || forward) ? web_browser_forward : web_browser; - return transparent ? _simpleTransparentWebBrowserPipeline : _simpleOpaqueWebBrowserPipeline; + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + state->setDepthTest(true, true, gpu::LESS_EQUAL); + // FIXME: do we need a testMaskDrawNoAA? + PrepareStencil::testMaskDrawShapeNoAA(*state); + state->setBlendFunction(transparent, + gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, + gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + state->setCullMode(gpu::State::CULL_NONE); + + _webPipelines[{ transparent, forward }] = gpu::Pipeline::create(gpu::Shader::createProgram(pipeline), state); + } + } + + return _webPipelines[{ transparent, forward }]; } void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool transparent, bool culled, bool unlit, bool depthBiased, bool isAntiAliased, bool forward) { @@ -2196,24 +2166,24 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transp std::call_once(once, [&]() { using namespace shader::render_utils::program; - _forwardSimpleShader = gpu::Shader::createProgram(forward_simple_textured); - _forwardTransparentShader = gpu::Shader::createProgram(forward_simple_textured_transparent); - _forwardUnlitShader = gpu::Shader::createProgram(forward_simple_textured_unlit); + _forwardSimpleShader = gpu::Shader::createProgram(simple_forward); + _forwardTransparentShader = gpu::Shader::createProgram(simple_translucent_forward); + _forwardUnlitShader = gpu::Shader::createProgram(simple_unlit_forward); - _simpleShader = gpu::Shader::createProgram(simple_textured); - _transparentShader = gpu::Shader::createProgram(simple_transparent_textured); - _unlitShader = gpu::Shader::createProgram(simple_textured_unlit); + _simpleShader = gpu::Shader::createProgram(simple); + _transparentShader = gpu::Shader::createProgram(simple_translucent); + _unlitShader = gpu::Shader::createProgram(simple_unlit); }); } else { static std::once_flag once; std::call_once(once, [&]() { using namespace shader::render_utils::program; - // FIXME: these aren't right... - _forwardSimpleFadeShader = gpu::Shader::createProgram(forward_simple_textured); - _forwardUnlitFadeShader = gpu::Shader::createProgram(forward_simple_textured_unlit); + // Fading is currently disabled during forward rendering + _forwardSimpleFadeShader = gpu::Shader::createProgram(simple_forward); + _forwardUnlitFadeShader = gpu::Shader::createProgram(simple_unlit_forward); - _simpleFadeShader = gpu::Shader::createProgram(simple_textured_fade); - _unlitFadeShader = gpu::Shader::createProgram(simple_textured_unlit_fade); + _simpleFadeShader = gpu::Shader::createProgram(simple_fade); + _unlitFadeShader = gpu::Shader::createProgram(simple_unlit_fade); }); } @@ -2281,8 +2251,7 @@ void renderInstances(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color if (isWire) { DependencyManager::get()->renderWireShapeInstances(batch, shape, data.count(), data.buffers[INSTANCE_COLOR_BUFFER]); - } - else { + } else { DependencyManager::get()->renderShapeInstances(batch, shape, data.count(), data.buffers[INSTANCE_COLOR_BUFFER]); } }); diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index a42b059a8c..b474e6c712 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -157,14 +157,6 @@ public: static void computeSimpleHullPointListForShape(int entityShape, const glm::vec3 &entityExtents, QVector &outPointList); - static uint8_t CUSTOM_PIPELINE_NUMBER; - static render::ShapePipelinePointer shapePipelineFactory(const render::ShapePlumber& plumber, const render::ShapeKey& key, gpu::Batch& batch); - static void registerShapePipeline() { - if (!CUSTOM_PIPELINE_NUMBER) { - CUSTOM_PIPELINE_NUMBER = render::ShapePipeline::registerCustomShapePipelineFactory(shapePipelineFactory); - } - } - int allocateID() { return _nextID++; } void releaseID(int id); static const int UNKNOWN_ID; @@ -176,15 +168,12 @@ public: static gpu::PipelinePointer getSimplePipeline(bool textured = false, bool transparent = false, bool culled = true, bool unlit = false, bool depthBias = false, bool fading = false, bool isAntiAliased = true, bool forward = false); - void bindWebBrowserProgram(gpu::Batch& batch, bool transparent = false); - gpu::PipelinePointer getWebBrowserProgram(bool transparent); + void bindWebBrowserProgram(gpu::Batch& batch, bool transparent, bool forward); + gpu::PipelinePointer getWebBrowserProgram(bool transparent, bool forward); + static std::map, gpu::PipelinePointer> _webPipelines; static void initializeShapePipelines(); - - render::ShapePipelinePointer getOpaqueShapePipeline() { assert(_simpleOpaquePipeline != nullptr); return _simpleOpaquePipeline; } - render::ShapePipelinePointer getTransparentShapePipeline() { assert(_simpleTransparentPipeline != nullptr); return _simpleTransparentPipeline; } - render::ShapePipelinePointer getForwardOpaqueShapePipeline() { assert(_forwardSimpleOpaquePipeline != nullptr); return _forwardSimpleOpaquePipeline; } - render::ShapePipelinePointer getForwardTransparentShapePipeline() { assert(_forwardSimpleTransparentPipeline != nullptr); return _forwardSimpleTransparentPipeline; } + render::ShapePipelinePointer getShapePipelinePointer(bool transparent, bool unlit, bool forward) { return _shapePipelines[std::make_tuple(transparent, unlit, forward)]; } // Static (instanced) geometry void renderShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer); @@ -195,17 +184,17 @@ public: void renderWireFadeShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer, gpu::BufferPointer& fadeBuffer1, gpu::BufferPointer& fadeBuffer2, gpu::BufferPointer& fadeBuffer3); - void renderSolidShapeInstance(RenderArgs* args, gpu::Batch& batch, Shape shape, const glm::vec4& color = glm::vec4(1), - const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline); + void renderSolidShapeInstance(RenderArgs* args, gpu::Batch& batch, Shape shape, const glm::vec4& color, + const render::ShapePipelinePointer& pipeline); void renderSolidShapeInstance(RenderArgs* args, gpu::Batch& batch, Shape shape, const glm::vec3& color, - const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline) { + const render::ShapePipelinePointer& pipeline) { renderSolidShapeInstance(args, batch, shape, glm::vec4(color, 1.0f), pipeline); } - void renderWireShapeInstance(RenderArgs* args, gpu::Batch& batch, Shape shape, const glm::vec4& color = glm::vec4(1), - const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline); + void renderWireShapeInstance(RenderArgs* args, gpu::Batch& batch, Shape shape, const glm::vec4& color, + const render::ShapePipelinePointer& pipeline); void renderWireShapeInstance(RenderArgs* args, gpu::Batch& batch, Shape shape, const glm::vec3& color, - const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline) { + const render::ShapePipelinePointer& pipeline) { renderWireShapeInstance(args, batch, shape, glm::vec4(color, 1.0f), pipeline); } @@ -217,33 +206,33 @@ public: const render::ShapePipelinePointer& pipeline); void renderSolidSphereInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, - const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline); + const render::ShapePipelinePointer& pipeline); void renderSolidSphereInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec3& color, - const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline) { + const render::ShapePipelinePointer& pipeline) { renderSolidSphereInstance(args, batch, glm::vec4(color, 1.0f), pipeline); } - + void renderWireSphereInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, - const render::ShapePipelinePointer& pipeline = _simpleWirePipeline); + const render::ShapePipelinePointer& pipeline); void renderWireSphereInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec3& color, - const render::ShapePipelinePointer& pipeline = _simpleWirePipeline) { + const render::ShapePipelinePointer& pipeline) { renderWireSphereInstance(args, batch, glm::vec4(color, 1.0f), pipeline); } - + void renderSolidCubeInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, - const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline); + const render::ShapePipelinePointer& pipeline); void renderSolidCubeInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec3& color, - const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline) { + const render::ShapePipelinePointer& pipeline) { renderSolidCubeInstance(args, batch, glm::vec4(color, 1.0f), pipeline); } - + void renderWireCubeInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, - const render::ShapePipelinePointer& pipeline = _simpleWirePipeline); + const render::ShapePipelinePointer& pipeline); void renderWireCubeInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec3& color, - const render::ShapePipelinePointer& pipeline = _simpleWirePipeline) { + const render::ShapePipelinePointer& pipeline) { renderWireCubeInstance(args, batch, glm::vec4(color, 1.0f), pipeline); } - + // Dynamic geometry void renderShape(gpu::Batch& batch, Shape shape); void renderWireShape(gpu::Batch& batch, Shape shape); @@ -467,21 +456,9 @@ private: static gpu::ShaderPointer _forwardSimpleFadeShader; static gpu::ShaderPointer _forwardUnlitFadeShader; - static render::ShapePipelinePointer _simpleOpaquePipeline; - static render::ShapePipelinePointer _simpleTransparentPipeline; - static render::ShapePipelinePointer _forwardSimpleOpaquePipeline; - static render::ShapePipelinePointer _forwardSimpleTransparentPipeline; - static render::ShapePipelinePointer _simpleOpaqueFadePipeline; - static render::ShapePipelinePointer _simpleTransparentFadePipeline; - static render::ShapePipelinePointer _simpleWirePipeline; - + static std::map, render::ShapePipelinePointer> _shapePipelines; static QHash _simplePrograms; - gpu::ShaderPointer _simpleOpaqueWebBrowserShader; - gpu::PipelinePointer _simpleOpaqueWebBrowserPipeline; - gpu::ShaderPointer _simpleTransparentWebBrowserShader; - gpu::PipelinePointer _simpleTransparentWebBrowserPipeline; - static render::ShapePipelinePointer getShapePipeline(bool textured = false, bool transparent = false, bool culled = true, bool unlit = false, bool depthBias = false, bool forward = false); static render::ShapePipelinePointer getFadingShapePipeline(bool textured = false, bool transparent = false, bool culled = true, diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/GlobalLight.slh similarity index 67% rename from libraries/render-utils/src/DeferredGlobalLight.slh rename to libraries/render-utils/src/GlobalLight.slh index 03ec18c321..6702270a5a 100644 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/GlobalLight.slh @@ -1,5 +1,5 @@ -<@if not DEFERRED_GLOBAL_LIGHT_SLH@> -<@def DEFERRED_GLOBAL_LIGHT_SLH@> +<@if not GLOBAL_LIGHT_SLH@> +<@def GLOBAL_LIGHT_SLH@> <@include graphics/Light.slh@> @@ -43,7 +43,6 @@ <@endfunc@> - <@func declareEvalAmbientGlobalColor()@> vec3 evalAmbientGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, float roughness) { <$prepareGlobalLight(position, normal)$> @@ -62,10 +61,11 @@ vec3 evalAmbientGlobalColor(mat4 invViewMat, float shadowAttenuation, float obsc <@endif@> vec3 evalAmbientSphereGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, -vec3 albedo, vec3 fresnel, float metallic, float roughness + vec3 albedo, vec3 fresnel, float metallic, float roughness <@if supportScattering@> , float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature -<@endif@> ) { +<@endif@> + ) { <$prepareGlobalLight(position, normal)$> @@ -76,19 +76,20 @@ vec3 albedo, vec3 fresnel, float metallic, float roughness vec3 ambientSpecular; evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance <@if supportScattering@> - ,scattering, midNormalCurvature, lowNormalCurvature -<@endif@> ); + , scattering, midNormalCurvature, lowNormalCurvature +<@endif@> + ); color += ambientDiffuse; color += ambientSpecular; - // Directional vec3 directionalDiffuse; vec3 directionalSpecular; evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation <@if supportScattering@> - ,scattering, midNormalCurvature, lowNormalCurvature -<@endif@> ); + , scattering, midNormalCurvature, lowNormalCurvature +<@endif@> + ); color += directionalDiffuse; color += directionalSpecular; @@ -97,9 +98,9 @@ vec3 albedo, vec3 fresnel, float metallic, float roughness <@endfunc@> -<@include Haze.slh@> +<@include graphics/Haze.slh@> -<@func declareEvalSkyboxGlobalColor(supportScattering)@> +<@func declareEvalSkyboxGlobalColor(supportScattering, computeHaze)@> <$declareLightingAmbient(_SCRIBE_NULL, 1, _SCRIBE_NULL, $supportScattering$)$> <$declareLightingDirectional($supportScattering$)$> @@ -108,13 +109,13 @@ vec3 albedo, vec3 fresnel, float metallic, float roughness <$declareDeferredCurvature()$> <@endif@> -vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, +vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, vec3 albedo, vec3 fresnel, float metallic, float roughness <@if supportScattering@> , float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature <@endif@> ) { - <$prepareGlobalLight(position, normal)$> + <$prepareGlobalLight(positionES, normalWS)$> SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS); @@ -123,25 +124,41 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu vec3 ambientSpecular; evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance <@if supportScattering@> - ,scattering, midNormalCurvature, lowNormalCurvature + , scattering, midNormalCurvature, lowNormalCurvature <@endif@> ); color += ambientDiffuse; color += ambientSpecular; + // Directional vec3 directionalDiffuse; vec3 directionalSpecular; evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation <@if supportScattering@> - ,scattering, midNormalCurvature, lowNormalCurvature + , scattering, midNormalCurvature, lowNormalCurvature <@endif@> ); color += directionalDiffuse; color += directionalSpecular; - // Attenuate the light if haze effect selected - if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) { - color = computeHazeColorKeyLightAttenuation(color, lightDirection, fragPositionWS); + // Haze + if (isHazeEnabled() > 0.0) { + if ((hazeParams.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) { + color = computeHazeColorKeyLightAttenuation(color, lightDirection, fragPositionWS); + } + +<@if computeHaze@> + if ((hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) { + vec4 hazeColor = computeHazeColor( + positionES, // fragment position in eye coordinates + fragPositionWS, // fragment position in world coordinates + invViewMat[3].xyz, // eye position in world coordinates + lightDirection // keylight direction vector in world coordinates + ); + + color = mix(color.rgb, hazeColor.rgb, hazeColor.a); + } +<@endif@> } return color; @@ -179,41 +196,10 @@ vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscur <$declareLightingAmbient(1, 1, 1)$> <$declareLightingDirectional()$> -vec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity, vec3 prevLighting) { - <$prepareGlobalLight(position, normal)$> - - SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS); - - color = prevLighting; - color += emissive * isEmissiveEnabled(); - - // Ambient - vec3 ambientDiffuse; - vec3 ambientSpecular; - evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance); - color += ambientDiffuse; - - // Directional - vec3 directionalDiffuse; - vec3 directionalSpecular; - evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation); - color += directionalDiffuse; - color += evalSpecularWithOpacity(ambientSpecular + directionalSpecular, opacity); - - return color; -} -<@endfunc@> - -<@func declareEvalGlobalLightingAlphaBlendedWithHaze()@> - -<$declareLightingAmbient(1, 1, 1)$> -<$declareLightingDirectional()$> - -vec3 evalGlobalLightingAlphaBlendedWithHaze( - mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, - vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) +vec3 evalGlobalLightingAlphaBlended( + mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, + vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) { - <$prepareGlobalLight(positionES, normalWS)$> SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS); @@ -234,23 +220,29 @@ vec3 evalGlobalLightingAlphaBlendedWithHaze( color += evalSpecularWithOpacity(ambientSpecular + directionalSpecular, opacity); // Haze - if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) { - vec4 hazeColor = computeHazeColor( - positionES, // fragment position in eye coordinates - fragPositionWS, // fragment position in world coordinates - invViewMat[3].xyz, // eye position in world coordinates - lightDirection // keylight direction vector in world coordinates - ); + if (isHazeEnabled() > 0.0) { + if ((hazeParams.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) { + color = computeHazeColorKeyLightAttenuation(color, lightDirection, fragPositionWS); + } - color = mix(color.rgb, hazeColor.rgb, hazeColor.a); + if ((hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) { + vec4 hazeColor = computeHazeColor( + positionES, // fragment position in eye coordinates + fragPositionWS, // fragment position in world coordinates + invViewMat[3].xyz, // eye position in world coordinates + lightDirection // keylight direction vector in world coordinates + ); + + color = mix(color.rgb, hazeColor.rgb, hazeColor.a); + } } return color; } -vec3 evalGlobalLightingAlphaBlendedWithHaze( - mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS, - vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) +vec3 evalGlobalLightingAlphaBlended( + mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS, + vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting) { <$fetchGlobalLight()$> @@ -271,15 +263,23 @@ vec3 evalGlobalLightingAlphaBlendedWithHaze( color += evalSpecularWithOpacity(ambientSpecular + directionalSpecular, opacity); // Haze - if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) { - vec4 hazeColor = computeHazeColor( - positionES, // fragment position in eye coordinates - positionWS, // fragment position in world coordinates - invViewMat[3].xyz, // eye position in world coordinates - lightDirection // keylight direction vector - ); + if (isHazeEnabled() > 0.0) { + vec3 fragPositionWS = vec3(invViewMat * vec4(positionES, 1.0)); - color = mix(color.rgb, hazeColor.rgb, hazeColor.a); + if ((hazeParams.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) { + color = computeHazeColorKeyLightAttenuation(color, lightDirection, fragPositionWS); + } + + if ((hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) { + vec4 hazeColor = computeHazeColor( + positionES, // fragment position in eye coordinates + fragPositionWS, // fragment position in world coordinates + invViewMat[3].xyz, // eye position in world coordinates + lightDirection // keylight direction vector in world coordinates + ); + + color = mix(color.rgb, hazeColor.rgb, hazeColor.a); + } } return color; diff --git a/libraries/render-utils/src/Haze.slf b/libraries/render-utils/src/Haze.slf index 170e69eb2d..899f36b8eb 100644 --- a/libraries/render-utils/src/Haze.slf +++ b/libraries/render-utils/src/Haze.slf @@ -15,11 +15,11 @@ <$declareDeferredFrameTransform()$> <@include graphics/Light.slh@> - -<@include LightingModel.slh@> <$declareLightBuffer()$> -<@include Haze.slh@> +<@include LightingModel.slh@> + +<@include graphics/Haze.slh@> LAYOUT(binding=RENDER_UTILS_TEXTURE_HAZE_LINEAR_DEPTH) uniform sampler2D linearDepthMap; diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp old mode 100644 new mode 100755 diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h old mode 100644 new mode 100755 diff --git a/libraries/render-utils/src/RenderCommonTask.cpp b/libraries/render-utils/src/RenderCommonTask.cpp index e5de6ccd27..9ea4ac9f3c 100644 --- a/libraries/render-utils/src/RenderCommonTask.cpp +++ b/libraries/render-utils/src/RenderCommonTask.cpp @@ -59,13 +59,21 @@ void DrawLayered3D::run(const RenderContextPointer& renderContext, const Inputs& const auto& inItems = inputs.get0(); const auto& lightingModel = inputs.get1(); - const auto jitter = inputs.get2(); + const auto& hazeFrame = inputs.get2(); + const auto jitter = inputs.get3(); config->setNumDrawn((int)inItems.size()); emit config->numDrawnChanged(); RenderArgs* args = renderContext->args; + graphics::HazePointer haze; + const auto& hazeStage = renderContext->args->_scene->getStage(); + if (hazeStage && hazeFrame->_hazes.size() > 0) { + // We use _hazes.back() here because the last haze object will always have haze disabled. + haze = hazeStage->getHaze(hazeFrame->_hazes.back()); + } + // Clear the framebuffer without stereo // Needs to be distinct from the other batch because using the clear call // while stereo is enabled triggers a warning @@ -96,6 +104,10 @@ void DrawLayered3D::run(const RenderContextPointer& renderContext, const Inputs& batch.setUniformBuffer(ru::Buffer::LightModel, lightingModel->getParametersBuffer()); batch.setResourceTexture(ru::Texture::AmbientFresnel, lightingModel->getAmbientFresnelLUT()); + if (haze) { + batch.setUniformBuffer(graphics::slot::buffer::Buffer::HazeParams, haze->getHazeParametersBuffer()); + } + if (_opaquePass) { renderStateSortShapes(renderContext, _shapePlumber, inItems, _maxDrawn); } else { @@ -128,52 +140,11 @@ void Blit::run(const RenderContextPointer& renderContext, const gpu::Framebuffer gpu::doInBatch("Blit", renderArgs->_context, [&](gpu::Batch& batch) { batch.setFramebuffer(blitFbo); - if (renderArgs->_renderMode == RenderArgs::MIRROR_RENDER_MODE) { - if (renderArgs->isStereo()) { - gpu::Vec4i srcRectLeft; - srcRectLeft.z = width / 2; - srcRectLeft.w = height; + gpu::Vec4i rect; + rect.z = width; + rect.w = height; - gpu::Vec4i srcRectRight; - srcRectRight.x = width / 2; - srcRectRight.z = width; - srcRectRight.w = height; - - gpu::Vec4i destRectLeft; - destRectLeft.x = srcRectLeft.z; - destRectLeft.z = srcRectLeft.x; - destRectLeft.y = srcRectLeft.y; - destRectLeft.w = srcRectLeft.w; - - gpu::Vec4i destRectRight; - destRectRight.x = srcRectRight.z; - destRectRight.z = srcRectRight.x; - destRectRight.y = srcRectRight.y; - destRectRight.w = srcRectRight.w; - - // Blit left to right and right to left in stereo - batch.blit(primaryFbo, srcRectRight, blitFbo, destRectLeft); - batch.blit(primaryFbo, srcRectLeft, blitFbo, destRectRight); - } else { - gpu::Vec4i srcRect; - srcRect.z = width; - srcRect.w = height; - - gpu::Vec4i destRect; - destRect.x = width; - destRect.y = 0; - destRect.z = 0; - destRect.w = height; - - batch.blit(primaryFbo, srcRect, blitFbo, destRect); - } - } else { - gpu::Vec4i rect; - rect.z = width; - rect.w = height; - - batch.blit(primaryFbo, rect, blitFbo, rect); - } + batch.blit(primaryFbo, rect, blitFbo, rect); }); } diff --git a/libraries/render-utils/src/RenderCommonTask.h b/libraries/render-utils/src/RenderCommonTask.h index 756445a30f..ec50fbf2cc 100644 --- a/libraries/render-utils/src/RenderCommonTask.h +++ b/libraries/render-utils/src/RenderCommonTask.h @@ -11,10 +11,9 @@ #include #include "LightStage.h" +#include "HazeStage.h" #include "LightingModel.h" - - class BeginGPURangeTimer { public: using JobModel = render::Job::ModelO; @@ -62,7 +61,7 @@ protected: class DrawLayered3D { public: - using Inputs = render::VaryingSet3; + using Inputs = render::VaryingSet4; using Config = DrawLayered3DConfig; using JobModel = render::Job::ModelI; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index e513fb7282..c26f3b613c 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -207,7 +207,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("RenderDeferred", deferredLightingInputs); // Similar to light stage, background stage has been filled by several potential render items and resolved for the frame in this job - const auto backgroundInputs = DrawBackgroundStage::Inputs(lightingModel, backgroundFrame).asVarying(); + const auto backgroundInputs = DrawBackgroundStage::Inputs(lightingModel, backgroundFrame, hazeFrame).asVarying(); task.addJob("DrawBackgroundDeferred", backgroundInputs); const auto drawHazeInputs = render::Varying(DrawHaze::Inputs(hazeFrame, lightingFramebuffer, linearDepthTarget, deferredFrameTransform, lightingModel, lightFrame)); @@ -225,8 +225,8 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("HighlightRangeTimer", outlineRangeTimer); // Layered Over (in front) - const auto inFrontOpaquesInputs = DrawLayered3D::Inputs(inFrontOpaque, lightingModel, jitter).asVarying(); - const auto inFrontTransparentsInputs = DrawLayered3D::Inputs(inFrontTransparent, lightingModel, jitter).asVarying(); + const auto inFrontOpaquesInputs = DrawLayered3D::Inputs(inFrontOpaque, lightingModel, hazeFrame, jitter).asVarying(); + const auto inFrontTransparentsInputs = DrawLayered3D::Inputs(inFrontTransparent, lightingModel, hazeFrame, jitter).asVarying(); task.addJob("DrawInFrontOpaque", inFrontOpaquesInputs, true); task.addJob("DrawInFrontTransparent", inFrontTransparentsInputs, false); @@ -254,7 +254,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto primaryFramebuffer = task.addJob("PrimaryBufferUpscale", toneMappedBuffer); // HUD Layer - const auto renderHUDLayerInputs = RenderHUDLayerTask::Input(primaryFramebuffer, lightingModel, hudOpaque, hudTransparent).asVarying(); + const auto renderHUDLayerInputs = RenderHUDLayerTask::Input(primaryFramebuffer, lightingModel, hudOpaque, hudTransparent, hazeFrame).asVarying(); task.addJob("RenderHUDLayer", renderHUDLayerInputs); } @@ -506,7 +506,7 @@ void RenderTransparentDeferred::run(const RenderContextPointer& renderContext, c if (hazeStage && hazeFrame->_hazes.size() > 0) { const auto& hazePointer = hazeStage->getHaze(hazeFrame->_hazes.front()); if (hazePointer) { - batch.setUniformBuffer(ru::Buffer::HazeParams, hazePointer->getHazeParametersBuffer()); + batch.setUniformBuffer(graphics::slot::buffer::Buffer::HazeParams, hazePointer->getHazeParametersBuffer()); } } diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp index d65ad18aa1..b6b17ee376 100755 --- a/libraries/render-utils/src/RenderForwardTask.cpp +++ b/libraries/render-utils/src/RenderForwardTask.cpp @@ -90,6 +90,7 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend const auto currentStageFrames = lightingStageInputs.get0(); const auto lightFrame = currentStageFrames[0]; const auto backgroundFrame = currentStageFrames[1]; + const auto hazeFrame = currentStageFrames[2]; const auto& zones = lightingStageInputs[1]; @@ -111,21 +112,21 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend task.addJob("PrepareStencil", scaledPrimaryFramebuffer); // Draw opaques forward - const auto opaqueInputs = DrawForward::Inputs(opaques, lightingModel).asVarying(); + const auto opaqueInputs = DrawForward::Inputs(opaques, lightingModel, hazeFrame).asVarying(); task.addJob("DrawOpaques", opaqueInputs, shapePlumber, true); // Similar to light stage, background stage has been filled by several potential render items and resolved for the frame in this job - const auto backgroundInputs = DrawBackgroundStage::Inputs(lightingModel, backgroundFrame).asVarying(); + const auto backgroundInputs = DrawBackgroundStage::Inputs(lightingModel, backgroundFrame, hazeFrame).asVarying(); task.addJob("DrawBackgroundForward", backgroundInputs); // Draw transparent objects forward - const auto transparentInputs = DrawForward::Inputs(transparents, lightingModel).asVarying(); + const auto transparentInputs = DrawForward::Inputs(transparents, lightingModel, hazeFrame).asVarying(); task.addJob("DrawTransparents", transparentInputs, shapePlumber, false); // Layered const auto nullJitter = Varying(glm::vec2(0.0f, 0.0f)); - const auto inFrontOpaquesInputs = DrawLayered3D::Inputs(inFrontOpaque, lightingModel, nullJitter).asVarying(); - const auto inFrontTransparentsInputs = DrawLayered3D::Inputs(inFrontTransparent, lightingModel, nullJitter).asVarying(); + const auto inFrontOpaquesInputs = DrawLayered3D::Inputs(inFrontOpaque, lightingModel, hazeFrame, nullJitter).asVarying(); + const auto inFrontTransparentsInputs = DrawLayered3D::Inputs(inFrontTransparent, lightingModel, hazeFrame, nullJitter).asVarying(); task.addJob("DrawInFrontOpaque", inFrontOpaquesInputs, true); task.addJob("DrawInFrontTransparent", inFrontTransparentsInputs, false); @@ -144,9 +145,9 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend // Just resolve the msaa const auto resolveInputs = ResolveFramebuffer::Inputs(scaledPrimaryFramebuffer, static_cast(nullptr)).asVarying(); - const auto resolvedFramebuffer = task.addJob("Resolve", resolveInputs); + const auto resolvedFramebuffer = task.addJob("Resolve", resolveInputs); - const auto toneMappedBuffer = resolvedFramebuffer; + const auto toneMappedBuffer = resolvedFramebuffer; #else const auto newResolvedFramebuffer = task.addJob("MakeResolvingFramebuffer"); @@ -167,7 +168,7 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend const auto primaryFramebuffer = task.addJob("PrimaryBufferUpscale", toneMappedBuffer); // HUD Layer - const auto renderHUDLayerInputs = RenderHUDLayerTask::Input(primaryFramebuffer, lightingModel, hudOpaque, hudTransparent).asVarying(); + const auto renderHUDLayerInputs = RenderHUDLayerTask::Input(primaryFramebuffer, lightingModel, hudOpaque, hudTransparent, hazeFrame).asVarying(); task.addJob("RenderHUDLayer", renderHUDLayerInputs); } @@ -258,11 +259,17 @@ void DrawForward::run(const RenderContextPointer& renderContext, const Inputs& i const auto& inItems = inputs.get0(); const auto& lightingModel = inputs.get1(); + const auto& hazeFrame = inputs.get2(); + + graphics::HazePointer haze; + const auto& hazeStage = renderContext->args->_scene->getStage(); + if (hazeStage && hazeFrame->_hazes.size() > 0) { + haze = hazeStage->getHaze(hazeFrame->_hazes.front()); + } gpu::doInBatch("DrawForward::run", args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; - // Setup projection glm::mat4 projMat; Transform viewMat; @@ -276,6 +283,10 @@ void DrawForward::run(const RenderContextPointer& renderContext, const Inputs& i batch.setUniformBuffer(ru::Buffer::LightModel, lightingModel->getParametersBuffer()); batch.setResourceTexture(ru::Texture::AmbientFresnel, lightingModel->getAmbientFresnelLUT()); + if (haze) { + batch.setUniformBuffer(graphics::slot::buffer::Buffer::HazeParams, haze->getHazeParametersBuffer()); + } + // From the lighting model define a global shapeKey ORED with individiual keys ShapeKey::Builder keyBuilder; if (lightingModel->isWireframeEnabled()) { diff --git a/libraries/render-utils/src/RenderForwardTask.h b/libraries/render-utils/src/RenderForwardTask.h index baf7f66c6c..2abf248692 100755 --- a/libraries/render-utils/src/RenderForwardTask.h +++ b/libraries/render-utils/src/RenderForwardTask.h @@ -96,7 +96,7 @@ private: class DrawForward{ public: - using Inputs = render::VaryingSet2; + using Inputs = render::VaryingSet3; using JobModel = render::Job::ModelI; DrawForward(const render::ShapePlumberPointer& shapePlumber, bool opaquePass) : _shapePlumber(shapePlumber), _opaquePass(opaquePass) {} diff --git a/libraries/render-utils/src/RenderHUDLayerTask.cpp b/libraries/render-utils/src/RenderHUDLayerTask.cpp index ac7a867366..743e59eebc 100644 --- a/libraries/render-utils/src/RenderHUDLayerTask.cpp +++ b/libraries/render-utils/src/RenderHUDLayerTask.cpp @@ -34,7 +34,7 @@ void CompositeHUD::run(const RenderContextPointer& renderContext, const gpu::Fra batch.setFramebuffer(inputs); } if (renderContext->args->_hudOperator) { - renderContext->args->_hudOperator(batch, renderContext->args->_hudTexture, renderContext->args->_renderMode == RenderArgs::RenderMode::MIRROR_RENDER_MODE); + renderContext->args->_hudOperator(batch, renderContext->args->_hudTexture); } }); #endif @@ -47,14 +47,15 @@ void RenderHUDLayerTask::build(JobModel& task, const render::Varying& input, ren const auto& lightingModel = inputs[1]; const auto& hudOpaque = inputs[2]; const auto& hudTransparent = inputs[3]; + const auto& hazeFrame = inputs[4]; // Composite the HUD and HUD overlays task.addJob("HUD", primaryFramebuffer); // And HUD Layer objects const auto nullJitter = Varying(glm::vec2(0.0f, 0.0f)); - const auto hudOpaquesInputs = DrawLayered3D::Inputs(hudOpaque, lightingModel, nullJitter).asVarying(); - const auto hudTransparentsInputs = DrawLayered3D::Inputs(hudTransparent, lightingModel, nullJitter).asVarying(); + const auto hudOpaquesInputs = DrawLayered3D::Inputs(hudOpaque, lightingModel, hazeFrame, nullJitter).asVarying(); + const auto hudTransparentsInputs = DrawLayered3D::Inputs(hudTransparent, lightingModel, hazeFrame, nullJitter).asVarying(); task.addJob("DrawHUDOpaque", hudOpaquesInputs, true); task.addJob("DrawHUDTransparent", hudTransparentsInputs, false); } diff --git a/libraries/render-utils/src/RenderHUDLayerTask.h b/libraries/render-utils/src/RenderHUDLayerTask.h index 78cd009636..c30b0498a8 100644 --- a/libraries/render-utils/src/RenderHUDLayerTask.h +++ b/libraries/render-utils/src/RenderHUDLayerTask.h @@ -10,7 +10,7 @@ #define hifi_RenderHUDLayerTask_h #include "LightingModel.h" - +#include "HazeStage.h" class CompositeHUD { public: @@ -25,7 +25,7 @@ public: class RenderHUDLayerTask { public: // Framebuffer where to draw, lighting model, opaque items, transparent items - using Input = render::VaryingSet4; + using Input = render::VaryingSet5; using JobModel = render::Task::ModelI; void build(JobModel& task, const render::Varying& input, render::Varying& output); diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 69a76cce00..d0ebe167f9 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -54,158 +54,125 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip using namespace shader::render_utils::program; using Key = render::ShapeKey; auto addPipeline = std::bind(&addPlumberPipeline, std::ref(plumber), _1, _2, _3, _4); - // TODO: Refactor this to use a filter - // Opaques - addPipeline( - Key::Builder().withMaterial(), - model, nullptr, nullptr); - addPipeline( - Key::Builder(), - simple_textured, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withUnlit(), - model_unlit, nullptr, nullptr); - addPipeline( - Key::Builder().withUnlit(), - simple_textured_unlit, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withTangents(), - model_normal_map, nullptr, nullptr); - // Same thing but with Fade on - addPipeline( - Key::Builder().withMaterial().withFade(), - model_fade, batchSetter, itemSetter); - addPipeline( - Key::Builder().withFade(), - simple_textured_fade, batchSetter, itemSetter); - addPipeline( - Key::Builder().withMaterial().withUnlit().withFade(), - model_unlit_fade, batchSetter, itemSetter); - addPipeline( - Key::Builder().withUnlit().withFade(), - simple_textured_unlit_fade, batchSetter, itemSetter); - addPipeline( - Key::Builder().withMaterial().withTangents().withFade(), - model_normal_map_fade, batchSetter, itemSetter); + // TOOD: build this list algorithmically so we don't have to maintain it + std::vector> pipelines = { + // Simple + { Key::Builder(), simple }, + { Key::Builder().withTranslucent(), simple_translucent }, + { Key::Builder().withUnlit(), simple_unlit }, + { Key::Builder().withTranslucent().withUnlit(), simple_translucent_unlit }, + // Simple Fade + { Key::Builder().withFade(), simple_fade }, + { Key::Builder().withTranslucent().withFade(), simple_translucent_fade }, + { Key::Builder().withUnlit().withFade(), simple_unlit_fade }, + { Key::Builder().withTranslucent().withUnlit().withFade(), simple_translucent_unlit_fade }, - // Translucents - addPipeline( - Key::Builder().withMaterial().withTranslucent(), - model_translucent, nullptr, nullptr); - addPipeline( - Key::Builder().withTranslucent(), - simple_transparent_textured, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withTranslucent().withUnlit(), - model_translucent_unlit, nullptr, nullptr); - addPipeline( - Key::Builder().withTranslucent().withUnlit(), - simple_transparent_textured_unlit, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withTranslucent().withTangents(), - model_translucent_normal_map, nullptr, nullptr); - addPipeline( - // FIXME: Ignore lightmap for translucents meshpart - Key::Builder().withMaterial().withTranslucent().withLightMap(), - model_translucent, nullptr, nullptr); - // Same thing but with Fade on - addPipeline( - Key::Builder().withMaterial().withTranslucent().withFade(), - model_translucent_fade, batchSetter, itemSetter); - addPipeline( - Key::Builder().withTranslucent().withFade(), - simple_transparent_textured_fade, batchSetter, itemSetter); - addPipeline( - Key::Builder().withMaterial().withTranslucent().withUnlit().withFade(), - model_translucent_unlit_fade, batchSetter, itemSetter); - addPipeline( - Key::Builder().withTranslucent().withUnlit().withFade(), - simple_transparent_textured_unlit_fade, batchSetter, itemSetter); - addPipeline( - Key::Builder().withMaterial().withTranslucent().withTangents().withFade(), - model_translucent_normal_map_fade, batchSetter, itemSetter); - addPipeline( - // FIXME: Ignore lightmap for translucents meshpart - Key::Builder().withMaterial().withTranslucent().withLightMap().withFade(), - model_translucent_fade, batchSetter, itemSetter); - // Lightmapped - addPipeline( - Key::Builder().withMaterial().withLightMap(), - model_lightmap, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withLightMap().withTangents(), - model_lightmap_normal_map, nullptr, nullptr); - // Same thing but with Fade on - addPipeline( - Key::Builder().withMaterial().withLightMap().withFade(), - model_lightmap_fade, batchSetter, itemSetter); - addPipeline( - Key::Builder().withMaterial().withLightMap().withTangents().withFade(), - model_lightmap_normal_map_fade, batchSetter, itemSetter); + // Unskinned + { Key::Builder().withMaterial(), model }, + { Key::Builder().withMaterial().withTangents(), model_normalmap }, + { Key::Builder().withMaterial().withTranslucent(), model_translucent }, + { Key::Builder().withMaterial().withTangents().withTranslucent(), model_normalmap_translucent }, + // Unskinned Unlit + { Key::Builder().withMaterial().withUnlit(), model_unlit }, + { Key::Builder().withMaterial().withTangents().withUnlit(), model_normalmap_unlit }, + { Key::Builder().withMaterial().withTranslucent().withUnlit(), model_translucent_unlit }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withUnlit(), model_normalmap_translucent_unlit }, + // Unskinned Lightmapped + { Key::Builder().withMaterial().withLightMap(), model_lightmap }, + { Key::Builder().withMaterial().withTangents().withLightMap(), model_normalmap_lightmap }, + { Key::Builder().withMaterial().withTranslucent().withLightMap(), model_translucent_lightmap }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withLightMap(), model_normalmap_translucent_lightmap }, + // Unskinned Fade + { Key::Builder().withMaterial().withFade(), model_fade }, + { Key::Builder().withMaterial().withTangents().withFade(), model_normalmap_fade }, + { Key::Builder().withMaterial().withTranslucent().withFade(), model_translucent_fade }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withFade(), model_normalmap_translucent_fade }, + // Unskinned Unlit Fade + { Key::Builder().withMaterial().withUnlit().withFade(), model_unlit_fade }, + { Key::Builder().withMaterial().withTangents().withUnlit().withFade(), model_normalmap_unlit_fade }, + { Key::Builder().withMaterial().withTranslucent().withUnlit().withFade(), model_translucent_unlit_fade }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withUnlit().withFade(), model_normalmap_translucent_unlit_fade }, + // Unskinned Lightmapped Fade + { Key::Builder().withMaterial().withLightMap().withFade(), model_lightmap_fade }, + { Key::Builder().withMaterial().withTangents().withLightMap().withFade(), model_normalmap_lightmap_fade }, + { Key::Builder().withMaterial().withTranslucent().withLightMap().withFade(), model_translucent_lightmap_fade }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withLightMap().withFade(), model_normalmap_translucent_lightmap_fade }, - // matrix palette skinned - addPipeline( - Key::Builder().withMaterial().withDeformed(), - deformed_model, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withDeformed().withTangents(), - deformed_model_normal_map, nullptr, nullptr); - // Same thing but with Fade on - addPipeline( - Key::Builder().withMaterial().withDeformed().withFade(), - deformed_model_fade, batchSetter, itemSetter); - addPipeline( - Key::Builder().withMaterial().withDeformed().withTangents().withFade(), - deformed_model_normal_map_fade, batchSetter, itemSetter); - // matrix palette skinned and translucent - addPipeline( - Key::Builder().withMaterial().withDeformed().withTranslucent(), - deformed_model_translucent, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withDeformed().withTranslucent().withTangents(), - deformed_model_normal_map_translucent, nullptr, nullptr); - // Same thing but with Fade on - addPipeline( - Key::Builder().withMaterial().withDeformed().withTranslucent().withFade(), - deformed_model_translucent_fade, batchSetter, itemSetter); - addPipeline( - Key::Builder().withMaterial().withDeformed().withTranslucent().withTangents().withFade(), - deformed_model_normal_map_translucent_fade, batchSetter, itemSetter); + // Matrix palette skinned + { Key::Builder().withMaterial().withDeformed(), model_deformed }, + { Key::Builder().withMaterial().withTangents().withDeformed(), model_normalmap_deformed }, + { Key::Builder().withMaterial().withTranslucent().withDeformed(), model_translucent_deformed }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withDeformed(), model_normalmap_translucent_deformed }, + // Matrix palette skinned Unlit + { Key::Builder().withMaterial().withUnlit().withDeformed(), model_unlit_deformed }, + { Key::Builder().withMaterial().withTangents().withUnlit().withDeformed(), model_normalmap_unlit_deformed }, + { Key::Builder().withMaterial().withTranslucent().withUnlit().withDeformed(), model_translucent_unlit_deformed }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withUnlit().withDeformed(), model_normalmap_translucent_unlit_deformed }, + // Matrix palette skinned Lightmapped + { Key::Builder().withMaterial().withLightMap().withDeformed(), model_lightmap_deformed }, + { Key::Builder().withMaterial().withTangents().withLightMap().withDeformed(), model_normalmap_lightmap_deformed }, + { Key::Builder().withMaterial().withTranslucent().withLightMap().withDeformed(), model_translucent_lightmap_deformed }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withLightMap().withDeformed(), model_normalmap_translucent_lightmap_deformed }, + // Matrix palette skinned Fade + { Key::Builder().withMaterial().withFade().withDeformed(), model_fade_deformed }, + { Key::Builder().withMaterial().withTangents().withFade().withDeformed(), model_normalmap_fade_deformed }, + { Key::Builder().withMaterial().withTranslucent().withFade().withDeformed(), model_translucent_fade_deformed }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withFade().withDeformed(), model_normalmap_translucent_fade_deformed }, + // Matrix palette skinned Unlit Fade + { Key::Builder().withMaterial().withUnlit().withFade().withDeformed(), model_unlit_fade_deformed }, + { Key::Builder().withMaterial().withTangents().withUnlit().withFade().withDeformed(), model_normalmap_unlit_fade_deformed }, + { Key::Builder().withMaterial().withTranslucent().withUnlit().withFade().withDeformed(), model_translucent_unlit_fade_deformed }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withUnlit().withFade().withDeformed(), model_normalmap_translucent_unlit_fade_deformed }, + // Matrix palette skinned Lightmapped Fade + { Key::Builder().withMaterial().withLightMap().withFade().withDeformed(), model_lightmap_fade_deformed }, + { Key::Builder().withMaterial().withTangents().withLightMap().withFade().withDeformed(), model_normalmap_lightmap_fade_deformed }, + { Key::Builder().withMaterial().withTranslucent().withLightMap().withFade().withDeformed(), model_translucent_lightmap_fade_deformed }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withLightMap().withFade().withDeformed(), model_normalmap_translucent_lightmap_fade_deformed }, - // dual quaternion skinned - addPipeline( - Key::Builder().withMaterial().withDeformed().withDualQuatSkinned(), - deformed_model_dq, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withDeformed().withDualQuatSkinned().withTangents(), - deformed_model_normal_map_dq, nullptr, nullptr); - // Same thing but with Fade on - addPipeline( - Key::Builder().withMaterial().withDeformed().withDualQuatSkinned().withFade(), - deformed_model_fade_dq, batchSetter, itemSetter); - addPipeline( - Key::Builder().withMaterial().withDeformed().withDualQuatSkinned().withTangents().withFade(), - deformed_model_normal_map_fade_dq, batchSetter, itemSetter); - // dual quaternion skinned and translucent - addPipeline( - Key::Builder().withMaterial().withDeformed().withDualQuatSkinned().withTranslucent(), - deformed_model_translucent_dq, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withDeformed().withDualQuatSkinned().withTranslucent().withTangents(), - deformed_model_normal_map_translucent_dq, nullptr, nullptr); - // Same thing but with Fade on - addPipeline( - Key::Builder().withMaterial().withDeformed().withDualQuatSkinned().withTranslucent().withFade(), - deformed_model_translucent_fade_dq, batchSetter, itemSetter); - addPipeline( - Key::Builder().withMaterial().withDeformed().withDualQuatSkinned().withTranslucent().withTangents().withFade(), - deformed_model_normal_map_translucent_fade_dq, batchSetter, itemSetter); + // Dual quaternion skinned + { Key::Builder().withMaterial().withDeformed().withDualQuatSkinned(), model_deformeddq }, + { Key::Builder().withMaterial().withTangents().withDeformed().withDualQuatSkinned(), model_normalmap_deformeddq }, + { Key::Builder().withMaterial().withTranslucent().withDeformed().withDualQuatSkinned(), model_translucent_deformeddq }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withDeformed().withDualQuatSkinned(), model_normalmap_translucent_deformeddq }, + // Dual quaternion skinned Unlit + { Key::Builder().withMaterial().withUnlit().withDeformed().withDualQuatSkinned(), model_unlit_deformeddq }, + { Key::Builder().withMaterial().withTangents().withUnlit().withDeformed().withDualQuatSkinned(), model_normalmap_unlit_deformeddq }, + { Key::Builder().withMaterial().withTranslucent().withUnlit().withDeformed().withDualQuatSkinned(), model_translucent_unlit_deformeddq }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withUnlit().withDeformed().withDualQuatSkinned(), model_normalmap_translucent_unlit_deformeddq }, + // Dual quaternion skinned Lightmapped + { Key::Builder().withMaterial().withLightMap().withDeformed().withDualQuatSkinned(), model_lightmap_deformeddq }, + { Key::Builder().withMaterial().withTangents().withLightMap().withDeformed().withDualQuatSkinned(), model_normalmap_lightmap_deformeddq }, + { Key::Builder().withMaterial().withTranslucent().withLightMap().withDeformed().withDualQuatSkinned(), model_translucent_lightmap_deformeddq }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withLightMap().withDeformed().withDualQuatSkinned(), model_normalmap_translucent_lightmap_deformeddq }, + // Dual quaternion skinned Fade + { Key::Builder().withMaterial().withFade().withDeformed().withDualQuatSkinned(), model_fade_deformeddq }, + { Key::Builder().withMaterial().withTangents().withFade().withDeformed().withDualQuatSkinned(), model_normalmap_fade_deformeddq }, + { Key::Builder().withMaterial().withTranslucent().withFade().withDeformed().withDualQuatSkinned(), model_translucent_fade_deformeddq }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withFade().withDeformed().withDualQuatSkinned(), model_normalmap_translucent_fade_deformeddq }, + // Dual quaternion skinned Unlit Fade + { Key::Builder().withMaterial().withUnlit().withFade().withDeformed().withDualQuatSkinned(), model_unlit_fade_deformeddq }, + { Key::Builder().withMaterial().withTangents().withUnlit().withFade().withDeformed().withDualQuatSkinned(), model_normalmap_unlit_fade_deformeddq }, + { Key::Builder().withMaterial().withTranslucent().withUnlit().withFade().withDeformed().withDualQuatSkinned(), model_translucent_unlit_fade_deformeddq }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withUnlit().withFade().withDeformed().withDualQuatSkinned(), model_normalmap_translucent_unlit_fade_deformeddq }, + // Dual quaternion skinned Lightmapped Fade + { Key::Builder().withMaterial().withLightMap().withFade().withDeformed().withDualQuatSkinned(), model_lightmap_fade_deformeddq }, + { Key::Builder().withMaterial().withTangents().withLightMap().withFade().withDeformed().withDualQuatSkinned(), model_normalmap_lightmap_fade_deformeddq }, + { Key::Builder().withMaterial().withTranslucent().withLightMap().withFade().withDeformed().withDualQuatSkinned(), model_translucent_lightmap_fade_deformeddq }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withLightMap().withFade().withDeformed().withDualQuatSkinned(), model_normalmap_translucent_lightmap_fade_deformeddq }, + }; + + for (auto& pipeline : pipelines) { + if (pipeline.first.build().isFaded()) { + addPipeline(pipeline.first, pipeline.second, batchSetter, itemSetter); + } else { + addPipeline(pipeline.first, pipeline.second, nullptr, nullptr); + } + } } void initForwardPipelines(ShapePlumber& plumber) { - using namespace shader::render_utils; - + using namespace shader::render_utils::program; using Key = render::ShapeKey; auto addPipelineBind = std::bind(&addPlumberPipeline, std::ref(plumber), _1, _2, _3, _4); @@ -218,38 +185,66 @@ void initForwardPipelines(ShapePlumber& plumber) { // Forward pipelines need the lightBatchSetter for opaques and transparents forceLightBatchSetter = true; - // Simple Opaques - addPipeline(Key::Builder(), program::forward_simple_textured); - addPipeline(Key::Builder().withUnlit(), program::forward_simple_textured_unlit); + // TOOD: build this list algorithmically so we don't have to maintain it + std::vector> pipelines = { + // Simple + { Key::Builder(), simple_forward }, + { Key::Builder().withTranslucent(), simple_translucent_forward }, + { Key::Builder().withUnlit(), simple_unlit_forward }, + { Key::Builder().withTranslucent().withUnlit(), simple_translucent_unlit_forward }, - // Simple Translucents - addPipeline(Key::Builder().withTranslucent(), program::forward_simple_textured_transparent); - addPipeline(Key::Builder().withTranslucent().withUnlit(), program::simple_transparent_textured_unlit); + // Unskinned + { Key::Builder().withMaterial(), model_forward }, + { Key::Builder().withMaterial().withTangents(), model_normalmap_forward }, + { Key::Builder().withMaterial().withTranslucent(), model_translucent_forward }, + { Key::Builder().withMaterial().withTangents().withTranslucent(), model_normalmap_translucent_forward }, + // Unskinned Unlit + { Key::Builder().withMaterial().withUnlit(), model_unlit_forward }, + { Key::Builder().withMaterial().withTangents().withUnlit(), model_normalmap_unlit_forward }, + { Key::Builder().withMaterial().withTranslucent().withUnlit(), model_translucent_unlit_forward }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withUnlit(), model_normalmap_translucent_unlit_forward }, + // Unskinned Lightmapped + { Key::Builder().withMaterial().withLightMap(), model_lightmap_forward }, + { Key::Builder().withMaterial().withTangents().withLightMap(), model_normalmap_lightmap_forward }, + { Key::Builder().withMaterial().withTranslucent().withLightMap(), model_translucent_lightmap_forward }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withLightMap(), model_normalmap_translucent_lightmap_forward }, - // Opaques - addPipeline(Key::Builder().withMaterial(), program::forward_model); - addPipeline(Key::Builder().withMaterial().withLightMap(), program::forward_model_lightmap); - addPipeline(Key::Builder().withMaterial().withUnlit(), program::forward_model_unlit); - addPipeline(Key::Builder().withMaterial().withTangents(), program::forward_model_normal_map); - addPipeline(Key::Builder().withMaterial().withTangents().withLightMap(), program::forward_model_normal_map_lightmap); + // Matrix palette skinned + { Key::Builder().withMaterial().withDeformed(), model_forward_deformed }, + { Key::Builder().withMaterial().withTangents().withDeformed(), model_normalmap_forward_deformed }, + { Key::Builder().withMaterial().withTranslucent().withDeformed(), model_translucent_forward_deformed }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withDeformed(), model_normalmap_translucent_forward_deformed }, + // Matrix palette skinned Unlit + { Key::Builder().withMaterial().withUnlit().withDeformed(), model_unlit_forward_deformed }, + { Key::Builder().withMaterial().withTangents().withUnlit().withDeformed(), model_normalmap_unlit_forward_deformed }, + { Key::Builder().withMaterial().withTranslucent().withUnlit().withDeformed(), model_translucent_unlit_forward_deformed }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withUnlit().withDeformed(), model_normalmap_translucent_unlit_forward_deformed }, + // Matrix palette skinned Lightmapped + { Key::Builder().withMaterial().withLightMap().withDeformed(), model_lightmap_forward_deformed }, + { Key::Builder().withMaterial().withTangents().withLightMap().withDeformed(), model_normalmap_lightmap_forward_deformed }, + { Key::Builder().withMaterial().withTranslucent().withLightMap().withDeformed(), model_translucent_lightmap_forward_deformed }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withLightMap().withDeformed(), model_normalmap_translucent_lightmap_forward_deformed }, - // Deformed Opaques - addPipeline(Key::Builder().withMaterial().withDeformed(), program::forward_deformed_model); - addPipeline(Key::Builder().withMaterial().withDeformed().withTangents(), program::forward_deformed_model_normal_map); - addPipeline(Key::Builder().withMaterial().withDeformed().withDualQuatSkinned(), program::forward_deformed_model_dq); - addPipeline(Key::Builder().withMaterial().withDeformed().withTangents().withDualQuatSkinned(), program::forward_deformed_model_normal_map_dq); + // Dual quaternion skinned + { Key::Builder().withMaterial().withDeformed().withDualQuatSkinned(), model_forward_deformeddq }, + { Key::Builder().withMaterial().withTangents().withDeformed().withDualQuatSkinned(), model_normalmap_forward_deformeddq }, + { Key::Builder().withMaterial().withTranslucent().withDeformed().withDualQuatSkinned(), model_translucent_forward_deformeddq }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withDeformed().withDualQuatSkinned(), model_normalmap_translucent_forward_deformeddq }, + // Dual quaternion skinned Unlit + { Key::Builder().withMaterial().withUnlit().withDeformed().withDualQuatSkinned(), model_unlit_forward_deformeddq }, + { Key::Builder().withMaterial().withTangents().withUnlit().withDeformed().withDualQuatSkinned(), model_normalmap_unlit_forward_deformeddq }, + { Key::Builder().withMaterial().withTranslucent().withUnlit().withDeformed().withDualQuatSkinned(), model_translucent_unlit_forward_deformeddq }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withUnlit().withDeformed().withDualQuatSkinned(), model_normalmap_translucent_unlit_forward_deformeddq }, + // Dual quaternion skinned Lightmapped + { Key::Builder().withMaterial().withLightMap().withDeformed().withDualQuatSkinned(), model_lightmap_forward_deformeddq }, + { Key::Builder().withMaterial().withTangents().withLightMap().withDeformed().withDualQuatSkinned(), model_normalmap_lightmap_forward_deformeddq }, + { Key::Builder().withMaterial().withTranslucent().withLightMap().withDeformed().withDualQuatSkinned(), model_translucent_lightmap_forward_deformeddq }, + { Key::Builder().withMaterial().withTangents().withTranslucent().withLightMap().withDeformed().withDualQuatSkinned(), model_normalmap_translucent_lightmap_forward_deformeddq }, + }; - // Translucents - addPipeline(Key::Builder().withMaterial().withTranslucent(), program::forward_model_translucent); - addPipeline(Key::Builder().withMaterial().withTranslucent().withTangents(), program::forward_model_normal_map_translucent); - - // Deformed Translucents - addPipeline(Key::Builder().withMaterial().withDeformed().withTranslucent(), program::forward_deformed_translucent); - addPipeline(Key::Builder().withMaterial().withDeformed().withTranslucent().withTangents(), program::forward_deformed_translucent_normal_map); - addPipeline(Key::Builder().withMaterial().withDeformed().withTranslucent().withDualQuatSkinned(), program::forward_deformed_translucent_dq); - addPipeline(Key::Builder().withMaterial().withDeformed().withTranslucent().withTangents().withDualQuatSkinned(), program::forward_deformed_translucent_normal_map_dq); - - // FIXME: incorrent pipelines for normal mapped + translucent models + for (auto& pipeline : pipelines) { + addPipeline(pipeline.first, pipeline.second); + } forceLightBatchSetter = false; } @@ -300,8 +295,7 @@ void addPlumberPipeline(ShapePlumber& plumber, baseBatchSetter(pipeline, batch, args); extraBatchSetter(pipeline, batch, args); }; - } - else { + } else { finalBatchSetter = baseBatchSetter; } plumber.addPipeline(builder.build(), program, state, finalBatchSetter, itemSetter); @@ -362,17 +356,17 @@ void initZPassPipelines(ShapePlumber& shapePlumber, gpu::StatePointer state, con shapePlumber.addPipeline( ShapeKey::Filter::Builder().withDeformed().withoutDualQuatSkinned().withoutFade(), - gpu::Shader::createProgram(deformed_model_shadow), state); + gpu::Shader::createProgram(model_shadow_deformed), state); shapePlumber.addPipeline( ShapeKey::Filter::Builder().withDeformed().withoutDualQuatSkinned().withFade(), - gpu::Shader::createProgram(deformed_model_shadow_fade), state, extraBatchSetter, itemSetter); + gpu::Shader::createProgram(model_shadow_fade_deformed), state, extraBatchSetter, itemSetter); shapePlumber.addPipeline( ShapeKey::Filter::Builder().withDeformed().withDualQuatSkinned().withoutFade(), - gpu::Shader::createProgram(deformed_model_shadow_dq), state); + gpu::Shader::createProgram(model_shadow_deformeddq), state); shapePlumber.addPipeline( ShapeKey::Filter::Builder().withDeformed().withDualQuatSkinned().withFade(), - gpu::Shader::createProgram(deformed_model_shadow_fade_dq), state, extraBatchSetter, itemSetter); + gpu::Shader::createProgram(model_shadow_fade_deformeddq), state, extraBatchSetter, itemSetter); } bool RenderPipelines::bindMaterial(graphics::MaterialPointer& material, gpu::Batch& batch, render::Args::RenderMode renderMode, bool enableTextures) { diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp old mode 100644 new mode 100755 index 5de89a11b5..f54b2e563e --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -56,7 +56,6 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende auto fadeEffect = DependencyManager::get(); initZPassPipelines(*shapePlumber, state, fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter()); } - const auto setupOutput = task.addJob("ShadowSetup", input); const auto queryResolution = setupOutput.getN(1); const auto shadowFrame = setupOutput.getN(3); @@ -318,16 +317,76 @@ RenderShadowSetup::RenderShadowSetup() : } void RenderShadowSetup::configure(const Config& configuration) { - setConstantBias(0, configuration.constantBias0); - setSlopeBias(0, configuration.slopeBias0); -#if SHADOW_CASCADE_MAX_COUNT>1 - setConstantBias(1, configuration.constantBias1); - setSlopeBias(1, configuration.slopeBias1); - setConstantBias(2, configuration.constantBias2); - setSlopeBias(2, configuration.slopeBias2); - setConstantBias(3, configuration.constantBias3); - setSlopeBias(3, configuration.slopeBias3); -#endif + distanceTriggeredByConfig = _globalMaxDistance != configuration.globalMaxDistance; + biasTriggeredByConfig = _biasInput != configuration.biasInput; + + // go back to using the config's default bias values if a change to any of those is triggered + if (constant0 != configuration.constantBias0 || slope0 != configuration.slopeBias0 || + constant1 != configuration.constantBias1 || slope1 != configuration.slopeBias1 || + constant2 != configuration.constantBias2 || slope2 != configuration.slopeBias2 || + constant3 != configuration.constantBias3 || slope3 != configuration.slopeBias3) { + constant0 = configuration.constantBias0; + slope0 = configuration.slopeBias0; + constant1 = configuration.constantBias1; + slope1 = configuration.slopeBias1; + constant2 = configuration.constantBias2; + slope2 = configuration.slopeBias2; + constant3 = configuration.constantBias3; + slope3 = configuration.slopeBias3; + changeInDefaultConfigValues = true; + distanceTriggeredByConfig = false; + biasTriggeredByConfig = false; + + setConstantBias(0, constant0); + setSlopeBias(0, slope0); + + #if SHADOW_CASCADE_MAX_COUNT > 1 + setConstantBias(1, constant1); + setConstantBias(2, constant2); + setConstantBias(3, constant3); + + setSlopeBias(1, slope1); + setSlopeBias(2, slope2); + setSlopeBias(3, slope3); + #endif + } + + // modify bias using single input and work in calculateBias() + if (distanceTriggeredByConfig) { + changeInDefaultConfigValues = false; + _globalMaxDistance = configuration.globalMaxDistance; + calculateBiases(); + } + if (biasTriggeredByConfig) { + changeInDefaultConfigValues = false; + _biasInput = configuration.biasInput; + calculateBiases(); + } +} + +void RenderShadowSetup::calculateBiases() { + // slope scaling values derived from ratio between original constantBias and slopeBias pairs + const std::array SLOPE_SCALES = {{ 2.7f, 3.0f, 3.7f, 3.5f }}; + const float CONVERT_BIAS = 100.0f; + const float MIN_SCALE_DIVISOR = 0.5f; + + // the bias is relative to resolution + // to remain consistent with the constant and slope bias values, the biasInput + // value is in the 0.0 - 1.0 range but needs to be scaled up for further calculations + float inverseResolution = 1.0f / (float)resolution; + int resolutionScale = DEFAULT_RESOLUTION * inverseResolution; + float convertedBias = _biasInput * (CONVERT_BIAS / resolutionScale); + std::array localConstants; + std::array localSlopes; + float scaleFactor = 1.0f; + + for (int i = 0; i < SHADOW_CASCADE_MAX_COUNT; i++) { + scaleFactor = convertedBias * (cacasdeDistances[0] / glm::max(MIN_SCALE_DIVISOR, cacasdeDistances[i + 4])) * inverseResolution; + localConstants[i] = cacasdeDistances[i] * scaleFactor; + localSlopes[i] = cacasdeDistances[i] * scaleFactor * SLOPE_SCALES[i]; + setConstantBias(i, localConstants[i]); + setSlopeBias(i, localSlopes[i]); + } } void RenderShadowSetup::setConstantBias(int cascadeIndex, float value) { @@ -368,20 +427,35 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, c if (!_globalShadowObject) { _globalShadowObject = std::make_shared(currentKeyLight, SHADOW_CASCADE_COUNT); } - + resolution = _globalShadowObject->MAP_SIZE; _globalShadowObject->setLight(currentKeyLight); _globalShadowObject->setKeylightFrustum(args->getViewFrustum(), SHADOW_FRUSTUM_NEAR, SHADOW_FRUSTUM_FAR); - + // if the max distance isn't altered externally, grab the value from the light + if (!distanceTriggeredByConfig && !biasTriggeredByConfig) { + _globalMaxDistance = currentKeyLight->getShadowsMaxDistance(); + } + _globalShadowObject->setMaxDistance(_globalMaxDistance); + auto& firstCascade = _globalShadowObject->getCascade(0); auto& firstCascadeFrustum = firstCascade.getFrustum(); unsigned int cascadeIndex; + for (cascadeIndex = 0; cascadeIndex < _globalShadowObject->getCascadeCount(); ++cascadeIndex) { + cacasdeDistances[cascadeIndex] = _globalShadowObject->getCascade(cascadeIndex).getMaxDistance(); + cacasdeDistances[cascadeIndex + 4] = _globalShadowObject->getCascade(cascadeIndex).getMinDistance(); + } + + if (!biasTriggeredByConfig && !distanceTriggeredByConfig && !changeInDefaultConfigValues) { + setBiasInput(currentKeyLight->getBiasInput()); + calculateBiases(); + } + // Adjust each cascade frustum const auto biasScale = currentKeyLight->getShadowsBiasScale(); for (cascadeIndex = 0; cascadeIndex < _globalShadowObject->getCascadeCount(); ++cascadeIndex) { auto& bias = _bias[cascadeIndex]; - _globalShadowObject->setKeylightCascadeFrustum(cascadeIndex, args->getViewFrustum(), - SHADOW_FRUSTUM_NEAR, SHADOW_FRUSTUM_FAR, + _globalShadowObject->setKeylightCascadeFrustum(cascadeIndex, args->getViewFrustum(), + SHADOW_FRUSTUM_NEAR, SHADOW_FRUSTUM_FAR, bias._constant, bias._slope * biasScale); } diff --git a/libraries/render-utils/src/RenderShadowTask.h b/libraries/render-utils/src/RenderShadowTask.h old mode 100644 new mode 100755 index ef469a7247..ceca28cec8 --- a/libraries/render-utils/src/RenderShadowTask.h +++ b/libraries/render-utils/src/RenderShadowTask.h @@ -50,7 +50,6 @@ signals: class RenderShadowTask { public: - // There is one AABox per shadow cascade using CascadeBoxes = render::VaryingArray; using Input = render::VaryingSet2; @@ -74,9 +73,11 @@ public: }; CullFunctor _cullFunctor; - }; +const float DEFAULT_BIAS_INPUT = 0.5f; +const float DEFAULT_MAX_DISTANCE = 40.0f; + class RenderShadowSetupConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(float constantBias0 MEMBER constantBias0 NOTIFY dirty) @@ -87,7 +88,12 @@ class RenderShadowSetupConfig : public render::Job::Config { Q_PROPERTY(float slopeBias1 MEMBER slopeBias1 NOTIFY dirty) Q_PROPERTY(float slopeBias2 MEMBER slopeBias2 NOTIFY dirty) Q_PROPERTY(float slopeBias3 MEMBER slopeBias3 NOTIFY dirty) + Q_PROPERTY(float biasInput MEMBER biasInput NOTIFY dirty) + Q_PROPERTY(float globalMaxDistance MEMBER globalMaxDistance NOTIFY dirty) + public: + float biasInput{ DEFAULT_BIAS_INPUT }; + float globalMaxDistance{ DEFAULT_MAX_DISTANCE }; float constantBias0{ 0.15f }; float constantBias1{ 0.15f }; @@ -114,7 +120,6 @@ public: void run(const render::RenderContextPointer& renderContext, const Input& input, Output& output); private: - ViewFrustumPointer _cameraFrustum; ViewFrustumPointer _coarseShadowFrustum; struct { @@ -125,8 +130,29 @@ private: LightStage::ShadowFrame::Object _globalShadowObject; LightStage::ShadowFramePointer _shadowFrameCache; + const int DEFAULT_RESOLUTION = 1024; + float _biasInput{ DEFAULT_BIAS_INPUT }; + float _globalMaxDistance{ DEFAULT_MAX_DISTANCE }; + int resolution{ DEFAULT_RESOLUTION }; + + // initialize with values from RenderShadowSetupConfig + float constant0{ 0.15f }; + float constant1{ 0.15f }; + float constant2{ 0.175f }; + float constant3{ 0.2f }; + float slope0{ 0.4f }; + float slope1{ 0.45f }; + float slope2{ 0.65f }; + float slope3{ 0.7f }; + bool changeInDefaultConfigValues{ false }; + bool distanceTriggeredByConfig{ false }; + bool biasTriggeredByConfig{ false }; + std::array cacasdeDistances; // 4 max then 4 min distances + void setConstantBias(int cascadeIndex, float value); void setSlopeBias(int cascadeIndex, float value); + void setBiasInput(float input) { _biasInput = input; } + void calculateBiases(); }; class RenderShadowCascadeSetup { diff --git a/libraries/render-utils/src/Shadow.slh b/libraries/render-utils/src/Shadow.slh old mode 100644 new mode 100755 index 94bec86b34..ac55bc95e5 --- a/libraries/render-utils/src/Shadow.slh +++ b/libraries/render-utils/src/Shadow.slh @@ -63,7 +63,7 @@ ShadowSampleOffsets evalShadowFilterOffsets(vec4 position) { coords.y += (index & 2) >> 1; #endif - // Offset for efficient PCF, see http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + // Offset for efficient PCF, see https://developer.nvidia.com/gpugems/GPUGems/gpugems_ch11.html ivec2 offset = coords & ivec2(1,1); offset.y = (offset.x+offset.y) & 1; diff --git a/libraries/render-utils/src/TextRenderer3D.cpp b/libraries/render-utils/src/TextRenderer3D.cpp index d3ea20273e..8c514df91d 100644 --- a/libraries/render-utils/src/TextRenderer3D.cpp +++ b/libraries/render-utils/src/TextRenderer3D.cpp @@ -67,11 +67,11 @@ float TextRenderer3D::getFontSize() const { } void TextRenderer3D::draw(gpu::Batch& batch, float x, float y, const QString& str, const glm::vec4& color, - const glm::vec2& bounds, bool forward) { + const glm::vec2& bounds, bool unlit, bool forward) { // The font does all the OpenGL work if (_font) { _color = color; - _font->drawString(batch, _drawInfo, str, _color, _effectType, { x, y }, bounds, forward); + _font->drawString(batch, _drawInfo, str, _color, _effectType, { x, y }, bounds, unlit, forward); } } diff --git a/libraries/render-utils/src/TextRenderer3D.h b/libraries/render-utils/src/TextRenderer3D.h index ce4dd9f9e5..8118aa883c 100644 --- a/libraries/render-utils/src/TextRenderer3D.h +++ b/libraries/render-utils/src/TextRenderer3D.h @@ -39,7 +39,7 @@ public: float getFontSize() const; // Pixel size void draw(gpu::Batch& batch, float x, float y, const QString& str, const glm::vec4& color, - const glm::vec2& bounds, bool forward); + const glm::vec2& bounds, bool unlit, bool forward); private: TextRenderer3D(const char* family, float pointSize, int weight = -1, bool italic = false, diff --git a/libraries/render-utils/src/deformed_model.slv b/libraries/render-utils/src/deformed_model.slv deleted file mode 100644 index 165b235e2a..0000000000 --- a/libraries/render-utils/src/deformed_model.slv +++ /dev/null @@ -1,53 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Hifi Engine Team. -// Copyright 2013 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 gpu/Inputs.slh@> -<@include gpu/Color.slh@> -<@include gpu/Transform.slh@> -<$declareStandardTransform()$> - -<@include graphics/MaterialTextures.slh@> -<$declareMaterialTexMapArrayBuffer()$> - -<@include MeshDeformer.slh@> -<$declareMeshDeformer(1, _SCRIBE_NULL, 1, _SCRIBE_NULL, 1)$> -<$declareMeshDeformerActivation(1, 1)$> - -<@include render-utils/ShaderConstants.h@> - -layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; - -void main(void) { - vec4 deformedPosition = vec4(0.0, 0.0, 0.0, 0.0); - vec3 deformedNormal = vec3(0.0, 0.0, 0.0); - evalMeshDeformer(inPosition, deformedPosition, inNormal.xyz, deformedNormal, - meshDeformer_doSkinning(_drawCallInfo.y), inSkinClusterIndex, inSkinClusterWeight, - meshDeformer_doBlendshape(_drawCallInfo.y), gl_VertexID); - - // pass along the color - _color.rgb = color_sRGBToLinear(inColor.rgb); - _color.a = inColor.a; - - // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToWorldAndEyeAndClipPos(cam, obj, deformedPosition, _positionWS, _positionES, gl_Position)$> - <$transformModelToWorldDir(cam, obj, deformedNormal, _normalWS.xyz)$> - - TexMapArray texMapArray = getTexMapArray(); - <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$> - <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord1, _positionWS, _texCoord01.zw)$> -} diff --git a/libraries/render-utils/src/deformed_model_dq.slv b/libraries/render-utils/src/deformed_model_dq.slv deleted file mode 100644 index 56ac1b6558..0000000000 --- a/libraries/render-utils/src/deformed_model_dq.slv +++ /dev/null @@ -1,53 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Hifi Engine Team. -// Copyright 2013 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 gpu/Inputs.slh@> -<@include gpu/Color.slh@> -<@include gpu/Transform.slh@> -<$declareStandardTransform()$> - -<@include graphics/MaterialTextures.slh@> -<$declareMaterialTexMapArrayBuffer()$> - -<@include MeshDeformer.slh@> -<$declareMeshDeformer(1, _SCRIBE_NULL, 1, 1, 1)$> -<$declareMeshDeformerActivation(1, 1)$> - -<@include render-utils/ShaderConstants.h@> - -layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; - -void main(void) { - vec4 deformedPosition = vec4(0.0, 0.0, 0.0, 0.0); - vec3 deformedNormal = vec3(0.0, 0.0, 0.0); - evalMeshDeformer(inPosition, deformedPosition, inNormal.xyz, deformedNormal, - meshDeformer_doSkinning(_drawCallInfo.y), inSkinClusterIndex, inSkinClusterWeight, - meshDeformer_doBlendshape(_drawCallInfo.y), gl_VertexID); - - // pass along the color - _color.rgb = color_sRGBToLinear(inColor.rgb); - _color.a = inColor.a; - - // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToWorldAndEyeAndClipPos(cam, obj, deformedPosition, _positionWS, _positionES, gl_Position)$> - <$transformModelToWorldDir(cam, obj, deformedNormal, _normalWS.xyz)$> - - TexMapArray texMapArray = getTexMapArray(); - <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$> - <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord1, _positionWS, _texCoord01.zw)$> -} diff --git a/libraries/render-utils/src/deformed_model_normal_map.slv b/libraries/render-utils/src/deformed_model_normal_map.slv deleted file mode 100644 index 85e164b639..0000000000 --- a/libraries/render-utils/src/deformed_model_normal_map.slv +++ /dev/null @@ -1,56 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Hifi Engine Team. -// Copyright 2013 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 gpu/Inputs.slh@> -<@include gpu/Color.slh@> -<@include gpu/Transform.slh@> -<$declareStandardTransform()$> - -<@include graphics/MaterialTextures.slh@> -<$declareMaterialTexMapArrayBuffer()$> - -<@include MeshDeformer.slh@> -<$declareMeshDeformer(1, 1, 1, _SCRIBE_NULL, 1)$> -<$declareMeshDeformerActivation(1, 1)$> - -<@include render-utils/ShaderConstants.h@> - -layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_TANGENT_WS) out vec3 _tangentWS; -layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; - -void main(void) { - vec4 deformedPosition = vec4(0.0, 0.0, 0.0, 0.0); - vec3 deformedNormal = vec3(0.0, 0.0, 0.0); - vec3 deformedTangent = vec3(0.0, 0.0, 0.0); - evalMeshDeformer(inPosition, deformedPosition, inNormal.xyz, deformedNormal, inTangent.xyz, deformedTangent, - meshDeformer_doSkinning(_drawCallInfo.y), inSkinClusterIndex, inSkinClusterWeight, - meshDeformer_doBlendshape(_drawCallInfo.y), gl_VertexID); - - // pass along the color - _color.rgb = color_sRGBToLinear(inColor.rgb); - _color.a = inColor.a; - - // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToWorldAndEyeAndClipPos(cam, obj, deformedPosition, _positionWS, _positionES, gl_Position)$> - <$transformModelToWorldDir(cam, obj, deformedNormal, _normalWS.xyz)$> - <$transformModelToWorldDir(cam, obj, deformedTangent, _tangentWS.xyz)$> - - TexMapArray texMapArray = getTexMapArray(); - <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$> - <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord1, _positionWS, _texCoord01.zw)$> -} diff --git a/libraries/render-utils/src/deformed_model_normal_map_dq.slv b/libraries/render-utils/src/deformed_model_normal_map_dq.slv deleted file mode 100644 index 807d343643..0000000000 --- a/libraries/render-utils/src/deformed_model_normal_map_dq.slv +++ /dev/null @@ -1,57 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Hifi Engine Team. -// Copyright 2013 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 gpu/Inputs.slh@> -<@include gpu/Color.slh@> -<@include gpu/Transform.slh@> -<@include render-utils/ShaderConstants.h@> -<$declareStandardTransform()$> - -<@include graphics/MaterialTextures.slh@> -<$declareMaterialTexMapArrayBuffer()$> - -<@include MeshDeformer.slh@> -<$declareMeshDeformer(1, 1, 1, 1, 1)$> -<$declareMeshDeformerActivation(1, 1)$> - -<@include render-utils/ShaderConstants.h@> - -layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_TANGENT_WS) out vec3 _tangentWS; -layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; - -void main(void) { - vec4 deformedPosition = vec4(0.0, 0.0, 0.0, 0.0); - vec3 deformedNormal = vec3(0.0, 0.0, 0.0); - vec3 deformedTangent = vec3(0.0, 0.0, 0.0); - evalMeshDeformer(inPosition, deformedPosition, inNormal.xyz, deformedNormal, inTangent.xyz, deformedTangent, - meshDeformer_doSkinning(_drawCallInfo.y), inSkinClusterIndex, inSkinClusterWeight, - meshDeformer_doBlendshape(_drawCallInfo.y), gl_VertexID); - - // pass along the color - _color.rgb = color_sRGBToLinear(inColor.rgb); - _color.a = inColor.a; - - // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToWorldAndEyeAndClipPos(cam, obj, deformedPosition, _positionWS, _positionES, gl_Position)$> - <$transformModelToWorldDir(cam, obj, deformedNormal, _normalWS.xyz)$> - <$transformModelToWorldDir(cam, obj, deformedTangent, _tangentWS.xyz)$> - - TexMapArray texMapArray = getTexMapArray(); - <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$> - <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord1, _positionWS, _texCoord01.zw)$> -} diff --git a/libraries/render-utils/src/deformed_model_shadow.slv b/libraries/render-utils/src/deformed_model_shadow.slv deleted file mode 100644 index 827fc69b32..0000000000 --- a/libraries/render-utils/src/deformed_model_shadow.slv +++ /dev/null @@ -1,52 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Hifi Engine Team. -// Copyright 2014 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 gpu/Inputs.slh@> -<@include gpu/Transform.slh@> -<$declareStandardTransform()$> - -<@include MeshDeformer.slh@> -<$declareMeshDeformer(_SCRIBE_NULL, _SCRIBE_NULL, 1, _SCRIBE_NULL, 1)$> -<$declareMeshDeformerActivation(1, 1)$> - -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> - -<$declareMaterialTexMapArrayBuffer()$> - -<@include render-utils/ShaderConstants.h@> - -layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; - -void main(void) { - vec4 deformedPosition = vec4(0.0, 0.0, 0.0, 0.0); - evalMeshDeformer(inPosition, deformedPosition, - meshDeformer_doSkinning(_drawCallInfo.y), inSkinClusterIndex, inSkinClusterWeight, - meshDeformer_doBlendshape(_drawCallInfo.y), gl_VertexID); - - // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, deformedPosition, gl_Position)$> - <$transformModelToWorldPos(obj, deformedPosition, _positionWS)$> - - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - _texCoord01 = vec4(0.0, 0.0, 0.0, 0.0); - // If we have an opacity mask than we need the first tex coord - if ((matKey & OPACITY_MASK_MAP_BIT) != 0) { - TexMapArray texMapArray = getTexMapArray(); - <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$> - } -} - diff --git a/libraries/render-utils/src/deformed_model_shadow_dq.slv b/libraries/render-utils/src/deformed_model_shadow_dq.slv deleted file mode 100644 index 646fc12ce9..0000000000 --- a/libraries/render-utils/src/deformed_model_shadow_dq.slv +++ /dev/null @@ -1,51 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Hifi Engine Team. -// Copyright 2014 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 gpu/Inputs.slh@> -<@include gpu/Transform.slh@> -<$declareStandardTransform()$> - -<@include MeshDeformer.slh@> -<$declareMeshDeformer(_SCRIBE_NULL, _SCRIBE_NULL, 1, 1, 1)$> -<$declareMeshDeformerActivation(1, 1)$> - -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> - -<$declareMaterialTexMapArrayBuffer()$> - -<@include render-utils/ShaderConstants.h@> - -layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; - -void main(void) { - vec4 deformedPosition = vec4(0.0, 0.0, 0.0, 0.0); - evalMeshDeformer(inPosition, deformedPosition, - meshDeformer_doSkinning(_drawCallInfo.y), inSkinClusterIndex, inSkinClusterWeight, - meshDeformer_doBlendshape(_drawCallInfo.y), gl_VertexID); - - // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, deformedPosition, gl_Position)$> - <$transformModelToWorldPos(obj, deformedPosition, _positionWS)$> - - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - _texCoord01 = vec4(0.0, 0.0, 0.0, 0.0); - // If we have an opacity mask than we need the first tex coord - if ((matKey & OPACITY_MASK_MAP_BIT) != 0) { - TexMapArray texMapArray = getTexMapArray(); - <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$> - } -} diff --git a/libraries/render-utils/src/deformed_simple.slv b/libraries/render-utils/src/deformed_simple.slv deleted file mode 100644 index ca587b79ef..0000000000 --- a/libraries/render-utils/src/deformed_simple.slv +++ /dev/null @@ -1,47 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Sam Gondelman on 5/15/19 -// Copyright 2019 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 gpu/Inputs.slh@> -<@include gpu/Color.slh@> -<@include gpu/Transform.slh@> -<$declareStandardTransform()$> - -<@include MeshDeformer.slh@> -<$declareMeshDeformer(1, _SCRIBE_NULL, 1, _SCRIBE_NULL, 1)$> -<$declareMeshDeformerActivation(1, 1)$> - -<@include render-utils/ShaderConstants.h@> - -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_NORMAL_MS) out vec3 _normalMS; -layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; -layout(location=RENDER_UTILS_ATTR_POSITION_MS) out vec4 _positionMS; -layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; - -void main(void) { - vec4 deformedPosition = vec4(0.0, 0.0, 0.0, 0.0); - vec3 deformedNormal = vec3(0.0, 0.0, 0.0); - evalMeshDeformer(inPosition, deformedPosition, inNormal.xyz, deformedNormal, - meshDeformer_doSkinning(_drawCallInfo.y), inSkinClusterIndex, inSkinClusterWeight, - meshDeformer_doBlendshape(_drawCallInfo.y), gl_VertexID); - - _color = color_sRGBAToLinear(inColor); - _texCoord01.xy = inTexCoord0.st; - _positionMS = inPosition; - _normalMS = inNormal.xyz; - - // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToEyeAndClipPos(cam, obj, deformedPosition, _positionES, gl_Position)$> - <$transformModelToWorldDir(cam, obj, deformedNormal, _normalWS)$> -} \ No newline at end of file diff --git a/libraries/render-utils/src/deformed_simple_dq.slv b/libraries/render-utils/src/deformed_simple_dq.slv deleted file mode 100644 index 825fc9a9f3..0000000000 --- a/libraries/render-utils/src/deformed_simple_dq.slv +++ /dev/null @@ -1,47 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Sam Gondelman on 5/15/19 -// Copyright 2019 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 gpu/Inputs.slh@> -<@include gpu/Color.slh@> -<@include gpu/Transform.slh@> -<$declareStandardTransform()$> - -<@include MeshDeformer.slh@> -<$declareMeshDeformer(1, _SCRIBE_NULL, 1, 1, 1)$> -<$declareMeshDeformerActivation(1, 1)$> - -<@include render-utils/ShaderConstants.h@> - -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_NORMAL_MS) out vec3 _normalMS; -layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; -layout(location=RENDER_UTILS_ATTR_POSITION_MS) out vec4 _positionMS; -layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; - -void main(void) { - vec4 deformedPosition = vec4(0.0, 0.0, 0.0, 0.0); - vec3 deformedNormal = vec3(0.0, 0.0, 0.0); - evalMeshDeformer(inPosition, deformedPosition, inNormal.xyz, deformedNormal, - meshDeformer_doSkinning(_drawCallInfo.y), inSkinClusterIndex, inSkinClusterWeight, - meshDeformer_doBlendshape(_drawCallInfo.y), gl_VertexID); - - _color = color_sRGBAToLinear(inColor); - _texCoord01.xy = inTexCoord0.st; - _positionMS = inPosition; - _normalMS = inNormal.xyz; - - // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToEyeAndClipPos(cam, obj, deformedPosition, _positionES, gl_Position)$> - <$transformModelToWorldDir(cam, obj, deformedNormal, _normalWS)$> -} \ No newline at end of file diff --git a/libraries/render-utils/src/directional_ambient_light.slf b/libraries/render-utils/src/directional_ambient_light.slf index b1cfc26c66..dd1b59f43e 100644 --- a/libraries/render-utils/src/directional_ambient_light.slf +++ b/libraries/render-utils/src/directional_ambient_light.slf @@ -11,15 +11,10 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // - - - <@include DeferredBufferRead.slh@> -<@include DeferredGlobalLight.slh@> <@include render-utils/ShaderConstants.h@> -<$declareEvalLightmappedColor()$> - +<@include GlobalLight.slh@> <$declareEvalAmbientSphereGlobalColor(supportScattering)$> layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; diff --git a/libraries/render-utils/src/directional_ambient_light_shadow.slf b/libraries/render-utils/src/directional_ambient_light_shadow.slf index 6b9fb80232..34018125af 100644 --- a/libraries/render-utils/src/directional_ambient_light_shadow.slf +++ b/libraries/render-utils/src/directional_ambient_light_shadow.slf @@ -11,15 +11,14 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // - -<@include Shadow.slh@> <@include DeferredBufferRead.slh@> -<@include DeferredGlobalLight.slh@> <@include render-utils/ShaderConstants.h@> -<$declareEvalLightmappedColor()$> +<@include GlobalLight.slh@> <$declareEvalAmbientSphereGlobalColor(isScattering)$> +<@include Shadow.slh@> + layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; #define _texCoord0 _texCoord01.xy #define _texCoord1 _texCoord01.zw diff --git a/libraries/render-utils/src/directional_skybox_light.slf b/libraries/render-utils/src/directional_skybox_light.slf index b820b3d17f..8e2b38b478 100644 --- a/libraries/render-utils/src/directional_skybox_light.slf +++ b/libraries/render-utils/src/directional_skybox_light.slf @@ -11,13 +11,11 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // - <@include DeferredBufferRead.slh@> -<@include DeferredGlobalLight.slh@> <@include render-utils/ShaderConstants.h@> -<$declareEvalLightmappedColor()$> -<$declareEvalSkyboxGlobalColor(isScattering)$> +<@include GlobalLight.slh@> +<$declareEvalSkyboxGlobalColor(isScattering, _SCRIBE_NULL)$> layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; #define _texCoord0 _texCoord01.xy diff --git a/libraries/render-utils/src/directional_skybox_light_shadow.slf b/libraries/render-utils/src/directional_skybox_light_shadow.slf index 8716d60d54..2f289ed00f 100644 --- a/libraries/render-utils/src/directional_skybox_light_shadow.slf +++ b/libraries/render-utils/src/directional_skybox_light_shadow.slf @@ -11,14 +11,13 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html //!> - -<@include Shadow.slh@> <@include DeferredBufferRead.slh@> -<@include DeferredGlobalLight.slh@> <@include render-utils/ShaderConstants.h@> -<$declareEvalLightmappedColor()$> -<$declareEvalSkyboxGlobalColor(isScattering)$> +<@include GlobalLight.slh@> +<$declareEvalSkyboxGlobalColor(isScattering, _SCRIBE_NULL)$> + +<@include Shadow.slh@> layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; #define _texCoord0 _texCoord01.xy @@ -35,7 +34,6 @@ void main(void) { vec3 worldLightDirection = getLightDirection(shadowLight); float shadowAttenuation = evalShadowAttenuation(worldLightDirection, worldPos, -viewPos.z, frag.normal); - // Light mapped or not ? if (frag.mode == FRAG_MODE_UNLIT || frag.mode == FRAG_MODE_LIGHTMAPPED) { discard; } else { diff --git a/libraries/render-utils/src/forward_grid.slf b/libraries/render-utils/src/forward_grid.slf deleted file mode 100644 index e34794bfed..0000000000 --- a/libraries/render-utils/src/forward_grid.slf +++ /dev/null @@ -1,40 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Sam Gondelman on 5/9/19 -// Copyright 2019 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 gpu/ShaderConstants.h@> -<@include gpu/Paint.slh@> - -struct Grid { - vec4 period; - vec4 offset; - vec4 edge; -}; - -LAYOUT(binding=0) uniform gridBuffer { - Grid grid; -}; - -layout(location=GPU_ATTR_TEXCOORD0) in vec2 varTexCoord0; -layout(location=GPU_ATTR_COLOR) in vec4 varColor; - -layout(location=0) out vec4 _fragColor0; - -void main(void) { - float alpha = mix(paintGridMajorMinor(varTexCoord0, grid.offset, grid.period, grid.edge), - paintGrid(varTexCoord0, grid.offset.xy, grid.period.xy, grid.edge.xy), - float(grid.edge.z == 0.0)); - - if (alpha < 0.0001) { - discard; - } - - _fragColor0 = vec4(varColor.xyz, 1.0); -} diff --git a/libraries/render-utils/src/forward_grid_translucent.slf b/libraries/render-utils/src/forward_grid_translucent.slf deleted file mode 100644 index df0494a22e..0000000000 --- a/libraries/render-utils/src/forward_grid_translucent.slf +++ /dev/null @@ -1,41 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Sam Gondelman on 5/9/19 -// Copyright 2019 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 gpu/ShaderConstants.h@> -<@include gpu/Paint.slh@> - -struct Grid { - vec4 period; - vec4 offset; - vec4 edge; -}; - -LAYOUT(binding=0) uniform gridBuffer { - Grid grid; -}; - -layout(location=GPU_ATTR_TEXCOORD0) in vec2 varTexCoord0; -layout(location=GPU_ATTR_COLOR) in vec4 varColor; - -layout(location=0) out vec4 _fragColor0; - -void main(void) { - float alpha = mix(paintGridMajorMinor(varTexCoord0, grid.offset, grid.period, grid.edge), - paintGrid(varTexCoord0, grid.offset.xy, grid.period.xy, grid.edge.xy), - float(grid.edge.z == 0.0)); - alpha *= varColor.w; - - if (alpha < 0.0001) { - discard; - } - - _fragColor0 = vec4(varColor.xyz, alpha); -} diff --git a/libraries/render-utils/src/forward_model.slf b/libraries/render-utils/src/forward_model.slf deleted file mode 100644 index daccd9c6d6..0000000000 --- a/libraries/render-utils/src/forward_model.slf +++ /dev/null @@ -1,83 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Sam Gateau on 2/15/2016. -// Copyright 2014 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 DefaultMaterials.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<@include ForwardGlobalLight.slh@> - -<$declareEvalSkyboxGlobalColor()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC, EMISSIVE, OCCLUSION)$> - -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -layout(location=0) out vec4 _fragColor0; - -void main(void) { - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> - - float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardTransparent(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - vec3 emissive = getMaterialEmissive(mat); - <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - vec3 fresnel = getFresnelF0(metallic, albedo); - - float occlusion = DEFAULT_OCCLUSION; - <$evalMaterialOcclusion(occlusionTex, matKey, occlusion)$>; - - vec3 fragPosition = _positionES.xyz; - vec3 fragNormal = normalize(_normalWS); - - TransformCamera cam = getTransformCamera(); - - vec4 color = vec4(evalSkyboxGlobalColor( - cam._viewInverse, - 1.0, - occlusion, - fragPosition, - fragNormal, - albedo, - fresnel, - metallic, - roughness), - opacity); - color.rgb += emissive * isEmissiveEnabled(); - - _fragColor0 = color; -} diff --git a/libraries/render-utils/src/forward_model_lightmap.slf b/libraries/render-utils/src/forward_model_lightmap.slf deleted file mode 100644 index aa1d6dc3b8..0000000000 --- a/libraries/render-utils/src/forward_model_lightmap.slf +++ /dev/null @@ -1,71 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Sam Gateau on 2/15/2016. -// Copyright 2014 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 DefaultMaterials.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<@include ForwardGlobalLight.slh@> - -<$declareEvalLightmappedColor()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC)$> -<$declareMaterialLightmap()$> - -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -layout(location=0) out vec4 _fragColor0; - -void main(void) { - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmap)$> - - float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardTransparent(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - vec3 fragNormal = normalize(_normalWS); - - TransformCamera cam = getTransformCamera(); - - vec4 color = vec4(evalLightmappedColor( - cam._viewInverse, - 1.0, - 1.0, - fragNormal, - albedo, - lightmap), - opacity); - - _fragColor0 = color; -} diff --git a/libraries/render-utils/src/forward_model_normal_map.slf b/libraries/render-utils/src/forward_model_normal_map.slf deleted file mode 100644 index 33e375c495..0000000000 --- a/libraries/render-utils/src/forward_model_normal_map.slf +++ /dev/null @@ -1,85 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Sam Gateau on 2/15/2016. -// Copyright 2014 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 DefaultMaterials.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<@include ForwardGlobalLight.slh@> - -<$declareEvalSkyboxGlobalColor()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC, EMISSIVE, OCCLUSION)$> - -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_TANGENT_WS) in vec3 _tangentWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -layout(location=0) out vec4 _fragColor0; - -void main(void) { - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> - - float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>; - <$discardTransparent(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - vec3 emissive = getMaterialEmissive(mat); - <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - vec3 fresnel = getFresnelF0(metallic, albedo); - - float occlusion = DEFAULT_OCCLUSION; - <$evalMaterialOcclusion(occlusionTex, matKey, occlusion)$>; - - vec3 fragPosition = _positionES.xyz; - vec3 fragNormal; - <$evalMaterialNormalLOD(fragPosition, normalTex, _normalWS, _tangentWS, fragNormal)$> - - TransformCamera cam = getTransformCamera(); - - vec4 color = vec4(evalSkyboxGlobalColor( - cam._viewInverse, - 1.0, - occlusion, - fragPosition, - fragNormal, - albedo, - fresnel, - metallic, - roughness), - opacity); - color.rgb += emissive * isEmissiveEnabled(); - - _fragColor0 = color; -} diff --git a/libraries/render-utils/src/forward_model_normal_map_lightmap.slf b/libraries/render-utils/src/forward_model_normal_map_lightmap.slf deleted file mode 100644 index c36f3d51c6..0000000000 --- a/libraries/render-utils/src/forward_model_normal_map_lightmap.slf +++ /dev/null @@ -1,74 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Sam Gateau on 2/15/2016. -// Copyright 2014 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 DefaultMaterials.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<@include ForwardGlobalLight.slh@> - -<$declareEvalLightmappedColor()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC)$> -<$declareMaterialLightmap()$> - -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_TANGENT_WS) in vec3 _tangentWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -layout(location=0) out vec4 _fragColor0; - -void main(void) { - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmap)$> - - float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardTransparent(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - vec3 fragPosition = _positionES.xyz; - vec3 fragNormal; - <$evalMaterialNormalLOD(fragPosition, normalTex, _normalWS, _tangentWS, fragNormal)$> - - TransformCamera cam = getTransformCamera(); - - vec4 color = vec4(evalLightmappedColor( - cam._viewInverse, - 1.0, - 1.0, - fragNormal, - albedo, - lightmap), - opacity); - - _fragColor0 = color; -} diff --git a/libraries/render-utils/src/forward_model_translucent.slf b/libraries/render-utils/src/forward_model_translucent.slf deleted file mode 100644 index 080ed7eea3..0000000000 --- a/libraries/render-utils/src/forward_model_translucent.slf +++ /dev/null @@ -1,81 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Sam Gateau on 2/15/2016. -// Copyright 2014 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 DefaultMaterials.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<@include ForwardGlobalLight.slh@> - -<$declareEvalGlobalLightingAlphaBlended()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC, EMISSIVE, OCCLUSION)$> - -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -layout(location=0) out vec4 _fragColor0; - -void main(void) { - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> - - float opacity = getMaterialOpacity(mat) * _color.a; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardInvisible(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - vec3 fresnel = getFresnelF0(metallic, albedo); - - float occlusion = DEFAULT_OCCLUSION; - <$evalMaterialOcclusion(occlusionTex, matKey, occlusion)$>; - - vec3 emissive = getMaterialEmissive(mat); - <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; - - vec3 fragPosition = _positionES.xyz; - vec3 fragNormal = normalize(_normalWS); - - TransformCamera cam = getTransformCamera(); - - _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze( - cam._viewInverse, - 1.0, - occlusion, - fragPosition, - fragNormal, - albedo, - fresnel, - metallic, - emissive, - roughness, opacity), - opacity); -} diff --git a/libraries/render-utils/src/forward_model_unlit.slf b/libraries/render-utils/src/forward_model_unlit.slf deleted file mode 100644 index ccd264f0bf..0000000000 --- a/libraries/render-utils/src/forward_model_unlit.slf +++ /dev/null @@ -1,42 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Sam Gateau on 5/5/2016. -// Copyright 2016 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 graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<@include LightingModel.slh@> - -<$declareMaterialTextures(ALBEDO)$> - -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -layout(location=0) out vec4 _fragColor0; - -void main(void) { - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$> - - float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardTransparent(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - _fragColor0 = vec4(albedo * isUnlitEnabled(), 1.0); -} diff --git a/libraries/render-utils/src/forward_parabola.slf b/libraries/render-utils/src/forward_parabola.slf deleted file mode 100644 index b0def6db6b..0000000000 --- a/libraries/render-utils/src/forward_parabola.slf +++ /dev/null @@ -1,18 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Sam Gondelman on 5/9/19 -// Copyright 2019 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 -// - -layout(location=0) in vec4 _color; - -layout(location=0) out vec4 _fragColor0; - -void main(void) { - _fragColor0 = _color; -} diff --git a/libraries/render-utils/src/forward_sdf_text3D.slf b/libraries/render-utils/src/forward_sdf_text3D.slf deleted file mode 100644 index 09b10c0c42..0000000000 --- a/libraries/render-utils/src/forward_sdf_text3D.slf +++ /dev/null @@ -1,57 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// sdf_text3D_transparent.frag -// fragment shader -// -// Created by Bradley Austin Davis on 2015-02-04 -// Based on fragment shader code from -// https://github.com/paulhoux/Cinder-Samples/blob/master/TextRendering/include/text/Text.cpp -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - -<@include DefaultMaterials.slh@> - -<@include ForwardGlobalLight.slh@> -<$declareEvalSkyboxGlobalColor()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -<@include render-utils/ShaderConstants.h@> - -<@include sdf_text3D.slh@> -<$declareEvalSDFSuperSampled()$> - -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw - -layout(location=0) out vec4 _fragColor0; - -void main() { - float a = evalSDFSuperSampled(_texCoord0); - - float alpha = a * _color.a; - if (alpha <= 0.0) { - discard; - } - - TransformCamera cam = getTransformCamera(); - vec3 fragPosition = _positionES.xyz; - - _fragColor0 = vec4(evalSkyboxGlobalColor( - cam._viewInverse, - 1.0, - DEFAULT_OCCLUSION, - fragPosition, - normalize(_normalWS), - _color.rgb, - DEFAULT_FRESNEL, - DEFAULT_METALLIC, - DEFAULT_ROUGHNESS), - 1.0); -} \ No newline at end of file diff --git a/libraries/render-utils/src/forward_simple.slf b/libraries/render-utils/src/forward_simple.slf deleted file mode 100644 index 7fa2b044d8..0000000000 --- a/libraries/render-utils/src/forward_simple.slf +++ /dev/null @@ -1,145 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// forward_simple.frag -// fragment shader -// -// Created by Andrzej Kapolka on 9/15/14. -// Copyright 2014 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 DefaultMaterials.slh@> - -<@include ForwardGlobalLight.slh@> -<$declareEvalSkyboxGlobalColor()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -// the interpolated normal -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_NORMAL_MS) in vec3 _normalMS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_POSITION_MS) in vec4 _positionMS; -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; - -// For retro-compatibility -#define _normal _normalWS -#define _modelNormal _normalMS -#define _position _positionMS -#define _eyePosition _positionES - -<@include procedural/ProceduralCommon.slh@> - -#line 1001 -//PROCEDURAL_BLOCK_BEGIN - -vec3 getProceduralColor() { - return _color.rgb; -} - -float getProceduralColors(inout vec3 diffuse, inout vec3 specular, inout float shininess) { - return 1.0; -} - -float getProceduralFragment(inout ProceduralFragment proceduralData) { - return 1.0; -} - -float getProceduralFragmentWithPosition(inout ProceduralFragmentWithPosition proceduralData) { - return 1.0; -} - -//PROCEDURAL_BLOCK_END - -layout(location=0) out vec4 _fragColor0; - -#line 2030 -void main(void) { - vec3 normal = normalize(_normalWS.xyz); - vec3 diffuse = _color.rgb; - float roughness = DEFAULT_ROUGHNESS; - float metallic = DEFAULT_METALLIC; - vec3 emissive = DEFAULT_EMISSIVE; - float occlusion = DEFAULT_OCCLUSION; - float scattering = DEFAULT_SCATTERING; - - float emissiveAmount = 0.0; - - TransformCamera cam = getTransformCamera(); - -#if defined(PROCEDURAL_V1) - diffuse = getProceduralColor().rgb; - emissiveAmount = 1.0; - emissive = vec3(1.0); -#elif defined(PROCEDURAL_V2) - vec3 specular = DEFAULT_SPECULAR; - float shininess = DEFAULT_SHININESS; - emissiveAmount = getProceduralColors(diffuse, specular, shininess); - roughness = max(0.0, 1.0 - shininess / 128.0); - metallic = length(specular); - emissive = vec3(clamp(emissiveAmount, 0.0, 1.0)); -#elif defined(PROCEDURAL_V3) || defined(PROCEDURAL_V4) -#if defined(PROCEDURAL_V3) - ProceduralFragment proceduralData = ProceduralFragment( -#else - vec4 position = cam._viewInverse * _positionES; - ProceduralFragmentWithPosition proceduralData = ProceduralFragmentWithPosition( - position.xyz, -#endif - normal, - diffuse, - DEFAULT_SPECULAR, - emissive, - 1.0, - roughness, - metallic, - occlusion, - scattering - ); - -#if defined(PROCEDURAL_V3) - emissiveAmount = getProceduralFragment(proceduralData); -#else - emissiveAmount = getProceduralFragmentWithPosition(proceduralData); -#endif - normal = proceduralData.normal; - diffuse = proceduralData.diffuse; - roughness = proceduralData.roughness; - metallic = proceduralData.metallic; - emissive = proceduralData.emissive; - occlusion = proceduralData.occlusion; - scattering = proceduralData.scattering; - -#if defined(PROCEDURAL_V4) - position = vec4(proceduralData.position, 1.0); - vec4 posClip = cam._projection * (cam._view * position); - gl_FragDepth = 0.5 * (posClip.z / posClip.w + 1.0); -#endif - -#endif - - if (emissiveAmount > 0.0) { - _fragColor0 = vec4(diffuse, 1.0); - } else { - vec3 fragPosition = _positionES.xyz; - vec3 fresnel = getFresnelF0(metallic, diffuse); - _fragColor0 = vec4(evalSkyboxGlobalColor( - cam._viewInverse, - 1.0, - occlusion, - fragPosition, - normal, - diffuse, - fresnel, - metallic, - roughness), - 1.0); - } -} diff --git a/libraries/render-utils/src/forward_simple_textured.slf b/libraries/render-utils/src/forward_simple_textured.slf deleted file mode 100644 index 373ab13d1a..0000000000 --- a/libraries/render-utils/src/forward_simple_textured.slf +++ /dev/null @@ -1,58 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// forward_simple_textured.frag -// fragment shader -// -// Created by Clément Brisset on 5/29/15. -// Copyright 2014 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 gpu/Color.slh@> -<@include DefaultMaterials.slh@> - -<@include ForwardGlobalLight.slh@> -<$declareEvalSkyboxGlobalColor()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -<@include render-utils/ShaderConstants.h@> - -LAYOUT(binding=0) uniform sampler2D originalTexture; - -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; - -layout(location=0) out vec4 _fragColor0; - -void main(void) { - vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); - vec3 albedo = _color.xyz * texel.xyz; - float metallic = DEFAULT_METALLIC; - - vec3 fresnel = getFresnelF0(metallic, albedo); - - TransformCamera cam = getTransformCamera(); - vec3 fragPosition = _positionES.xyz; - - _fragColor0 = vec4(evalSkyboxGlobalColor( - cam._viewInverse, - 1.0, - DEFAULT_OCCLUSION, - fragPosition, - normalize(_normalWS), - albedo, - fresnel, - metallic, - DEFAULT_ROUGHNESS), - 1.0); -} \ No newline at end of file diff --git a/libraries/render-utils/src/forward_simple_textured_transparent.slf b/libraries/render-utils/src/forward_simple_textured_transparent.slf deleted file mode 100644 index 1b5047507b..0000000000 --- a/libraries/render-utils/src/forward_simple_textured_transparent.slf +++ /dev/null @@ -1,60 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// forward_simple_textured_transparent.frag -// fragment shader -// -// Created by Clément Brisset on 5/29/15. -// Copyright 2014 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 gpu/Color.slh@> -<@include DefaultMaterials.slh@> - -<@include ForwardGlobalLight.slh@> -<$declareEvalGlobalLightingAlphaBlended()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -<@include render-utils/ShaderConstants.h@> - -LAYOUT(binding=0) uniform sampler2D originalTexture; - -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw - -layout(location=0) out vec4 _fragColor0; - -void main(void) { - vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); - vec3 albedo = _color.xyz * texel.xyz; - float alpha = _color.a * texel.a; - float metallic = DEFAULT_METALLIC; - - vec3 fresnel = getFresnelF0(metallic, albedo); - - TransformCamera cam = getTransformCamera(); - vec3 fragPosition = _positionES.xyz; - - _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze( - cam._viewInverse, - 1.0, - DEFAULT_OCCLUSION, - fragPosition, - normalize(_normalWS), - albedo, - fresnel, - metallic, - DEFAULT_EMISSIVE, - DEFAULT_ROUGHNESS, alpha), - alpha); -} \ No newline at end of file diff --git a/libraries/render-utils/src/forward_simple_textured_unlit.slf b/libraries/render-utils/src/forward_simple_textured_unlit.slf deleted file mode 100644 index ddbc5ae4d7..0000000000 --- a/libraries/render-utils/src/forward_simple_textured_unlit.slf +++ /dev/null @@ -1,35 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// forward_simple_textured_unlit.frag -// fragment shader -// -// Created by Clément Brisset on 5/29/15. -// Copyright 2014 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 LightingModel.slh@> -<@include gpu/Color.slh@> - -<@include render-utils/ShaderConstants.h@> - -layout(location=0) out vec4 _fragColor0; - -// the albedo texture -LAYOUT(binding=0) uniform sampler2D originalTexture; - -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw - -void main(void) { - vec4 texel = texture(originalTexture, _texCoord0.st); - float colorAlpha = _color.a * texel.a; - - _fragColor0 = vec4(_color.rgb * texel.rgb * isUnlitEnabled(), colorAlpha); -} \ No newline at end of file diff --git a/libraries/render-utils/src/glowLine.slf b/libraries/render-utils/src/glowLine.slf deleted file mode 100644 index c65d8d6488..0000000000 --- a/libraries/render-utils/src/glowLine.slf +++ /dev/null @@ -1,34 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Bradley Austin Davis on 2016/07/05 -// Copyright 2013-2016 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 render-utils/ShaderConstants.h@> - -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=0) in float distanceFromCenter; -layout(location=0) out vec4 _fragColor; - -void main(void) { - // The incoming value actually ranges from -1 to 1, so modify it - // so that it goes from 0 -> 1 -> 0 with the solid alpha being at - // the center of the line - float alpha = 1.0 - abs(distanceFromCenter); - - // Convert from a linear alpha curve to a sharp peaked one - alpha = _color.a * pow(alpha, 10.0); - - // Drop everything where the curve falls off to nearly nothing - if (alpha <= 0.05) { - discard; - } - - // Emit the color - _fragColor = vec4(_color.rgb, alpha); -} diff --git a/libraries/render-utils/src/glowLine.slv b/libraries/render-utils/src/glowLine.slv deleted file mode 100644 index 1bcb25817c..0000000000 --- a/libraries/render-utils/src/glowLine.slv +++ /dev/null @@ -1,61 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Bradley Austin Davis on 2016/07/05 -// Copyright 2013-2016 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 gpu/Transform.slh@> -<@include render-utils/ShaderConstants.h@> - -<$declareStandardTransform()$> - -struct LineData { - vec4 p1; - vec4 p2; - vec4 color; - float width; -}; - -LAYOUT_STD140(binding=0) uniform LineDataBuffer { - LineData _lineData; -}; - -layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; -// the distance from the center in 'quad space' -layout(location=0) out float distanceFromCenter; - -void main(void) { - _color = _lineData.color; - - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - - vec4 p1eye, p2eye; - <$transformModelToEyePos(cam, obj, _lineData.p1, p1eye)$> - <$transformModelToEyePos(cam, obj, _lineData.p2, p2eye)$> - p1eye /= p1eye.w; - p2eye /= p2eye.w; - - // Find the line direction - vec3 v1 = normalize(p1eye.xyz - p2eye.xyz); - // Find the vector from the eye to one of the points - vec3 v2 = normalize(p1eye.xyz); - // The orthogonal vector is the cross product of these two - vec3 orthogonal = cross(v1, v2) * _lineData.width; - - // Deteremine which end to emit based on the vertex id (even / odd) - vec4 eye = mix(p2eye, p1eye, float(gl_VertexID % 2 == 0)); - - // Add or subtract the orthogonal vector based on a different vertex ID - // calculation - distanceFromCenter = 1.0 - 2.0 * float(gl_VertexID < 2); - eye.xyz += distanceFromCenter * orthogonal; - - // Finally, put the eyespace vertex into clip space - <$transformEyeToClipPos(cam, eye, gl_Position)$> -} diff --git a/libraries/render-utils/src/grid.slf b/libraries/render-utils/src/grid.slf index 50c420bc10..8d54dfef4a 100644 --- a/libraries/render-utils/src/grid.slf +++ b/libraries/render-utils/src/grid.slf @@ -1,5 +1,6 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> +// <$_SCRIBE_FILENAME$> // Generated on <$_SCRIBE_DATE$> // // Created by Zach Pomerantz on 2/16/2016. @@ -9,11 +10,15 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include DeferredBufferWrite.slh@> - <@include gpu/ShaderConstants.h@> <@include gpu/Paint.slh@> +<@if not HIFI_USE_FORWARD@> + <@include DeferredBufferWrite.slh@> +<@else@> + layout(location=0) out vec4 _fragColor0; +<@endif@> + struct Grid { vec4 period; vec4 offset; @@ -28,13 +33,21 @@ layout(location=GPU_ATTR_TEXCOORD0) in vec2 varTexCoord0; layout(location=GPU_ATTR_COLOR) in vec4 varColor; void main(void) { - float alpha = mix(paintGridMajorMinor(varTexCoord0, grid.offset, grid.period, grid.edge), + float gridLine = mix(paintGridMajorMinor(varTexCoord0, grid.offset, grid.period, grid.edge), paintGrid(varTexCoord0, grid.offset.xy, grid.period.xy, grid.edge.xy), float(grid.edge.z == 0.0)); - - if (alpha < 0.0001) { + if (gridLine <= 0.0) { discard; } - packDeferredFragmentUnlit(vec3(1.0, 0.0, 0.0), 1.0, varColor.xyz); +<@if not HIFI_USE_FORWARD@> + vec3 NORMAL = vec3(1.0, 0.0, 0.0); + <@if not HIFI_USE_TRANSLUCENT@> + packDeferredFragmentUnlit(NORMAL, 1.0, varColor.rgb); + <@else@> + packDeferredFragmentTranslucent(NORMAL, varColor.a, varColor.rgb, DEFAULT_ROUGHNESS); + <@endif@> +<@else@> + _fragColor0 = varColor; +<@endif@> } diff --git a/libraries/render-utils/src/grid_translucent.slf b/libraries/render-utils/src/grid_translucent.slf deleted file mode 100644 index bb61126991..0000000000 --- a/libraries/render-utils/src/grid_translucent.slf +++ /dev/null @@ -1,41 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Sam Gondelman on 12/22/18 -// Copyright 2018 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 DeferredBufferWrite.slh@> - -<@include gpu/ShaderConstants.h@> -<@include gpu/Paint.slh@> - -struct Grid { - vec4 period; - vec4 offset; - vec4 edge; -}; - -LAYOUT(binding=0) uniform gridBuffer { - Grid grid; -}; - -layout(location=GPU_ATTR_TEXCOORD0) in vec2 varTexCoord0; -layout(location=GPU_ATTR_COLOR) in vec4 varColor; - -void main(void) { - float alpha = mix(paintGridMajorMinor(varTexCoord0, grid.offset, grid.period, grid.edge), - paintGrid(varTexCoord0, grid.offset.xy, grid.period.xy, grid.edge.xy), - float(grid.edge.z == 0.0)); - alpha *= varColor.w; - - if (alpha < 0.0001) { - discard; - } - - packDeferredFragmentTranslucent(vec3(1.0, 0.0, 0.0), alpha, varColor.xyz, DEFAULT_ROUGHNESS); -} diff --git a/libraries/render-utils/src/hmd_ui.slf b/libraries/render-utils/src/hmd_ui.slf index 6895a90f9e..af19ef1c06 100644 --- a/libraries/render-utils/src/hmd_ui.slf +++ b/libraries/render-utils/src/hmd_ui.slf @@ -12,6 +12,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // <@include render-utils/ShaderConstants.h@> +<@include gpu/Color.slh@> LAYOUT(binding=0) uniform sampler2D hudTexture; @@ -36,5 +37,5 @@ void main() { discard; } - fragColor0 = color; + fragColor0 = color_sRGBAToLinear(color); } \ No newline at end of file diff --git a/libraries/render-utils/src/hmd_ui.slv b/libraries/render-utils/src/hmd_ui.slv index 6e782d1672..75423d1882 100644 --- a/libraries/render-utils/src/hmd_ui.slv +++ b/libraries/render-utils/src/hmd_ui.slv @@ -29,7 +29,7 @@ LAYOUT_STD140(binding=0) uniform hudBuffer { layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; void main() { - _texCoord01.xy = inTexCoord0.st; + _texCoord01 = vec4(inTexCoord0.st, 0.0, 0.0); // standard transform TransformCamera cam = getTransformCamera(); diff --git a/libraries/render-utils/src/model.slf b/libraries/render-utils/src/model.slf index edf5064324..3e4711dac8 100644 --- a/libraries/render-utils/src/model.slf +++ b/libraries/render-utils/src/model.slf @@ -1,6 +1,6 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> +// <$_SCRIBE_FILENAME$> // Generated on <$_SCRIBE_DATE$> // // Created by Andrzej Kapolka on 5/6/14. @@ -10,55 +10,320 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include DeferredBufferWrite.slh@> <@include graphics/Material.slh@> <@include graphics/MaterialTextures.slh@> <@include render-utils/ShaderConstants.h@> -<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC, EMISSIVE, OCCLUSION, SCATTERING)$> +<@if not HIFI_USE_SHADOW@> + <@if HIFI_USE_FORWARD or HIFI_USE_TRANSLUCENT@> + <@include DefaultMaterials.slh@> + <@include GlobalLight.slh@> + <@if HIFI_USE_LIGHTMAP@> + <$declareEvalLightmappedColor()$> + <@elif HIFI_USE_TRANSLUCENT@> + <@if not HIFI_USE_FORWARD@> + <@include LightLocal.slh@> + <@endif@> + <$declareEvalGlobalLightingAlphaBlended()$> + <@else@> + <$declareEvalSkyboxGlobalColor(_SCRIBE_NULL, HIFI_USE_FORWARD)$> + <@endif@> + <@include gpu/Transform.slh@> + <$declareStandardCameraTransform()$> + layout(location=0) out vec4 _fragColor0; + <@else@> + <@include DeferredBufferWrite.slh@> + <@endif@> +<@else@> + layout(location=0) out vec4 _fragColor0; +<@endif@> +<@if HIFI_USE_UNLIT@> + <@include LightingModel.slh@> +<@endif@> + +<@if HIFI_USE_SHADOW or HIFI_USE_UNLIT@> + <$declareMaterialTextures(ALBEDO)$> +<@else@> + <@if not HIFI_USE_LIGHTMAP@> + <@if HIFI_USE_NORMALMAP and HIFI_USE_TRANSLUCENT@> + <$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL , METALLIC, EMISSIVE, OCCLUSION)$> + <@elif HIFI_USE_NORMALMAP@> + <$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL , METALLIC, EMISSIVE, OCCLUSION, SCATTERING)$> + <@elif HIFI_USE_TRANSLUCENT@> + <$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL , METALLIC, EMISSIVE, OCCLUSION)$> + <@else@> + <$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL , METALLIC, EMISSIVE, OCCLUSION, SCATTERING)$> + <@endif@> + <@else@> + <@if HIFI_USE_NORMALMAP@> + <$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC)$> + <@else@> + <$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC)$> + <@endif@> + <$declareMaterialLightmap()$> + <@endif@> +<@endif@> + +<@if HIFI_USE_FADE@> + <@include Fade.slh@> + <$declareFadeFragment()$> +<@endif@> + +layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; #define _texCoord0 _texCoord01.xy #define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; +<@if not HIFI_USE_SHADOW@> + layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; + layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; + layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; + <@if HIFI_USE_NORMALMAP@> + layout(location=RENDER_UTILS_ATTR_TANGENT_WS) in vec3 _tangentWS; + <@endif@> +<@endif@> void main(void) { +<@if HIFI_USE_FADE@> + <@if not HIFI_USE_SHADOW@> + vec3 fadeEmissive; + FadeObjectParams fadeParams; + <$fetchFadeObjectParams(fadeParams)$> + applyFade(fadeParams, _positionWS.xyz, fadeEmissive); + <@else@> + FadeObjectParams fadeParams; + <$fetchFadeObjectParams(fadeParams)$> + applyFadeClip(fadeParams, _positionWS.xyz); + <@endif@> +<@endif@> + Material mat = getMaterial(); BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex, scatteringTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> +<@if HIFI_USE_SHADOW or HIFI_USE_UNLIT@> + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$> - float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardTransparent(opacity)$>; + <@if HIFI_USE_TRANSLUCENT@> + float opacity = getMaterialOpacity(mat) * _color.a; + <@else@> + float opacity = 1.0; + <@endif@> + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + <@if HIFI_USE_TRANSLUCENT@> + <$discardInvisible(opacity)$>; + <@else@> + <$discardTransparent(opacity)$>; + <@endif@> - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; + <@if not HIFI_USE_SHADOW@> + vec3 albedo = getMaterialAlbedo(mat); + <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; + albedo *= _color.rgb; + <@if HIFI_USE_FADE@> + albedo += fadeEmissive; + <@endif@> + <@endif@> - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; + <@if HIFI_USE_SHADOW@> + _fragColor0 = vec4(1.0); + <@elif HIFI_USE_TRANSLUCENT or HIFI_USE_FORWARD@> + _fragColor0 = vec4(albedo * isUnlitEnabled(), opacity); + <@else@> + packDeferredFragmentUnlit( + normalize(_normalWS), + opacity, + albedo * isUnlitEnabled()); + <@endif@> +<@else@> + <@if not HIFI_USE_LIGHTMAP@> + <@if HIFI_USE_NORMALMAP and HIFI_USE_TRANSLUCENT@> + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex, _SCRIBE_NULL)$> + <@elif HIFI_USE_NORMALMAP@> + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex, scatteringTex)$> + <@elif HIFI_USE_TRANSLUCENT@> + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex, _SCRIBE_NULL)$> + <@else@> + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex, scatteringTex)$> + <@endif@> + <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> + <@else@> + <@if HIFI_USE_NORMALMAP@> + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex)$> + <@else@> + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex)$> + <@endif@> + <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmap)$> + <@endif@> - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; + <@if HIFI_USE_TRANSLUCENT@> + float opacity = getMaterialOpacity(mat) * _color.a; + <@else@> + float opacity = 1.0; + <@endif@> + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + <@if HIFI_USE_TRANSLUCENT@> + <$discardInvisible(opacity)$>; + <@else@> + <$discardTransparent(opacity)$>; + <@endif@> - vec3 emissive = getMaterialEmissive(mat); - <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; + vec3 albedo = getMaterialAlbedo(mat); + <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; + albedo *= _color.rgb; - float occlusion = DEFAULT_OCCLUSION; - <$evalMaterialOcclusion(occlusionTex, matKey, occlusion)$>; + float roughness = getMaterialRoughness(mat); + <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - float scattering = getMaterialScattering(mat); - <$evalMaterialScattering(scatteringTex, scattering, matKey, scattering)$>; + float metallic = getMaterialMetallic(mat); + <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - packDeferredFragment( - normalize(_normalWS), - opacity, - albedo, - roughness, - metallic, - emissive, - occlusion, - scattering); + <@if not HIFI_USE_LIGHTMAP@> + vec3 emissive = getMaterialEmissive(mat); + <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; + + float occlusion = DEFAULT_OCCLUSION; + <$evalMaterialOcclusion(occlusionTex, matKey, occlusion)$>; + + <@if not HIFI_USE_TRANSLUCENT@> + float scattering = getMaterialScattering(mat); + <$evalMaterialScattering(scatteringTex, scattering, matKey, scattering)$>; + <@endif@> + <@endif@> + + <@if HIFI_USE_NORMALMAP@> + vec3 fragNormalWS; + <$evalMaterialNormalLOD(_positionES, normalTex, _normalWS, _tangentWS, fragNormalWS)$> + <@else@> + vec3 fragNormalWS = _normalWS; + <@endif@> + fragNormalWS = normalize(fragNormalWS); + + <@if HIFI_USE_FORWARD@> + TransformCamera cam = getTransformCamera(); + vec3 fresnel = getFresnelF0(metallic, albedo); + <@if not HIFI_USE_TRANSLUCENT@> + <@if not HIFI_USE_LIGHTMAP@> + vec4 color = vec4(evalSkyboxGlobalColor( + cam._viewInverse, + 1.0, + occlusion, + _positionES.xyz, + fragNormalWS, + albedo, + fresnel, + metallic, + roughness), + opacity); + color.rgb += emissive * isEmissiveEnabled(); + _fragColor0 = color; + <@else@> + _fragColor0 = vec4(evalLightmappedColor( + cam._viewInverse, + 1.0, + DEFAULT_OCCLUSION, + fragNormalWS, + albedo, + lightmap), + opacity); + <@endif@> + <@else@> + <@if not HIFI_USE_LIGHTMAP@> + _fragColor0 = vec4(evalGlobalLightingAlphaBlended( + cam._viewInverse, + 1.0, + occlusion, + _positionES.xyz, + fragNormalWS, + albedo, + fresnel, + metallic, + emissive, + roughness, opacity), + opacity); + <@else@> + _fragColor0 = vec4(evalLightmappedColor( + cam._viewInverse, + 1.0, + DEFAULT_OCCLUSION, + fragNormalWS, + albedo, + lightmap), + opacity); + <@endif@> + <@endif@> + <@else@> + <@if not HIFI_USE_TRANSLUCENT@> + <@if not HIFI_USE_LIGHTMAP@> + packDeferredFragment( + fragNormalWS, + opacity, + albedo, + roughness, + metallic, + emissive + <@if HIFI_USE_FADE@> + + fadeEmissive + <@endif@> + , + occlusion, + scattering); + <@else@> + packDeferredFragmentLightmap( + fragNormalWS, + evalOpaqueFinalAlpha(getMaterialOpacity(mat), opacity), + albedo, + roughness, + metallic, + lightmap + <@if HIFI_USE_FADE@> + + fadeEmissive + <@endif@> + ); + <@endif@> + <@else@> + TransformCamera cam = getTransformCamera(); + <@if not HIFI_USE_LIGHTMAP@> + vec3 fresnel = getFresnelF0(metallic, albedo); + + vec3 fragPositionWS = _positionWS.xyz; + vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS; + vec3 fragToEyeDirWS = normalize(fragToEyeWS); + SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS); + + vec4 localLighting = vec4(0.0); + <$fetchClusterInfo(_positionWS)$>; + if (hasLocalLights(numLights, clusterPos, dims)) { + localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS, + metallic, fresnel, albedo, 0.0, + vec4(0), vec4(0), opacity); + } + + _fragColor0 = vec4(evalGlobalLightingAlphaBlended( + cam._viewInverse, + 1.0, + occlusion, + _positionES.xyz, + fragNormalWS, + albedo, + fresnel, + metallic, + emissive + <@if HIFI_USE_FADE@> + + fadeEmissive + <@endif@> + , + surfaceWS, opacity, localLighting.rgb), + opacity); + <@else@> + _fragColor0 = vec4(evalLightmappedColor( + cam._viewInverse, + 1.0, + DEFAULT_OCCLUSION, + fragNormalWS, + albedo, + lightmap), + opacity); + <@endif@> + <@endif@> + <@endif@> +<@endif@> } diff --git a/libraries/render-utils/src/model.slv b/libraries/render-utils/src/model.slv index 88cbd1e18c..319711eac2 100644 --- a/libraries/render-utils/src/model.slv +++ b/libraries/render-utils/src/model.slv @@ -1,10 +1,10 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> +// <$_SCRIBE_FILENAME$> +// Generated on <$_SCRIBE_DATE$> // -// Created by Hifi Engine Team. -// Copyright 2013 High Fidelity, Inc. +// Created by Hifi Engine Team +// Copyright 2019 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 @@ -12,32 +12,94 @@ <@include gpu/Inputs.slh@> <@include gpu/Color.slh@> -<@include gpu/Transform.slh@> -<@include graphics/MaterialTextures.slh@> - -<$declareStandardTransform()$> - -<$declareMaterialTexMapArrayBuffer()$> - <@include render-utils/ShaderConstants.h@> +<@include gpu/Transform.slh@> +<$declareStandardTransform()$> + +<@include graphics/MaterialTextures.slh@> +<$declareMaterialTexMapArrayBuffer()$> + +<@if HIFI_USE_DEFORMED or HIFI_USE_DEFORMEDDQ@> + <@include MeshDeformer.slh@> + <@if HIFI_USE_DEFORMED@> + <@if HIFI_USE_SHADOW@> + <$declareMeshDeformer(_SCRIBE_NULL, _SCRIBE_NULL, 1, _SCRIBE_NULL, 1)$> + <@elif not HIFI_USE_NORMALMAP@> + <$declareMeshDeformer(1, _SCRIBE_NULL, 1, _SCRIBE_NULL, 1)$> + <@else@> + <$declareMeshDeformer(1, 1, 1, _SCRIBE_NULL, 1)$> + <@endif@> + <@else@> + <@if HIFI_USE_SHADOW@> + <$declareMeshDeformer(_SCRIBE_NULL, _SCRIBE_NULL, 1, 1, 1)$> + <@elif not HIFI_USE_NORMALMAP@> + <$declareMeshDeformer(1, _SCRIBE_NULL, 1, 1, 1)$> + <@else@> + <$declareMeshDeformer(1, 1, 1, 1, 1)$> + <@endif@> + <@endif@> + <$declareMeshDeformerActivation(1, 1)$> +<@endif@> + layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; +<@if not HIFI_USE_SHADOW@> + layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; + layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; + layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; + <@if HIFI_USE_NORMALMAP@> + layout(location=RENDER_UTILS_ATTR_TANGENT_WS) out vec3 _tangentWS; + <@endif@> +<@endif@> void main(void) { - _color.rgb = color_sRGBToLinear(inColor.rgb); - _color.a = inColor.a; + vec4 positionMS = inPosition; + vec3 normalMS = inNormal.xyz; + vec3 tangentMS = inTangent.xyz; + +<@if HIFI_USE_DEFORMED or HIFI_USE_DEFORMEDDQ@> + evalMeshDeformer(inPosition, positionMS, + <@if not HIFI_USE_SHADOW@> + inNormal.xyz, normalMS, + <@if HIFI_USE_NORMALMAP@> + inTangent.xyz, tangentMS, + <@endif@> + <@endif@> + meshDeformer_doSkinning(_drawCallInfo.y), inSkinClusterIndex, inSkinClusterWeight, + meshDeformer_doBlendshape(_drawCallInfo.y), gl_VertexID); +<@endif@> - // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToWorldAndEyeAndClipPos(cam, obj, inPosition, _positionWS, _positionES, gl_Position)$> - <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normalWS)$> +<@if not HIFI_USE_SHADOW@> + <$transformModelToWorldAndEyeAndClipPos(cam, obj, positionMS, _positionWS, _positionES, gl_Position)$> + <$transformModelToWorldDir(cam, obj, normalMS, _normalWS)$> +<@else@> + <$transformModelToClipPos(cam, obj, positionMS, gl_Position)$> + <$transformModelToWorldPos(obj, positionMS, _positionWS)$> +<@endif@> - TexMapArray texMapArray = getTexMapArray(); - <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$> - <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord1, _positionWS, _texCoord01.zw)$> +<@if HIFI_USE_NORMALMAP@> + <$transformModelToWorldDir(cam, obj, tangentMS, _tangentWS)$> +<@endif@> + +<@if HIFI_USE_SHADOW@> + Material mat = getMaterial(); + BITFIELD matKey = getMaterialKey(mat); + // If we have an opacity mask than we need the first tex coord + if ((matKey & OPACITY_MASK_MAP_BIT) != 0) { + TexMapArray texMapArray = getTexMapArray(); + <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$> + _texCoord01.zw = vec2(0.0); + } else { + _texCoord01 = vec4(0.0); + } +<@else@> + _color = color_sRGBAToLinear(inColor); + + TexMapArray texMapArray = getTexMapArray(); + <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$> + <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord1, _positionWS, _texCoord01.zw)$> +<@endif@> } diff --git a/libraries/render-utils/src/model_fade.slf b/libraries/render-utils/src/model_fade.slf deleted file mode 100644 index e931ec4cf0..0000000000 --- a/libraries/render-utils/src/model_fade.slf +++ /dev/null @@ -1,73 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Olivier Prat on 06/05/17. -// 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 DeferredBufferWrite.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC, EMISSIVE, OCCLUSION, SCATTERING)$> - -<@include Fade.slh@> -<$declareFadeFragment()$> - -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -void main(void) { - vec3 fadeEmissive; - FadeObjectParams fadeParams; - <$fetchFadeObjectParams(fadeParams)$> - applyFade(fadeParams, _positionWS.xyz, fadeEmissive); - - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex, scatteringTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> - - float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardTransparent(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - vec3 emissive = getMaterialEmissive(mat); - <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; - - float occlusion = DEFAULT_OCCLUSION; - <$evalMaterialOcclusion(occlusionTex, matKey, occlusion)$>; - - float scattering = getMaterialScattering(mat); - <$evalMaterialScattering(scatteringTex, scattering, matKey, scattering)$>; - - packDeferredFragment( - normalize(_normalWS), - opacity, - albedo, - roughness, - metallic, - emissive + fadeEmissive, - occlusion, - scattering); -} diff --git a/libraries/render-utils/src/model_lightmap.slf b/libraries/render-utils/src/model_lightmap.slf deleted file mode 100644 index 1be247e3e9..0000000000 --- a/libraries/render-utils/src/model_lightmap.slf +++ /dev/null @@ -1,50 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Samuel Gateau on 11/19/14. -// Copyright 2014 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 DeferredBufferWrite.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC)$> -<$declareMaterialLightmap()$> - -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -void main(void) { - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmap)$> - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - packDeferredFragmentLightmap( - normalize(_normalWS), - evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedoTex.a), - albedo, - roughness, - metallic, - lightmap); -} diff --git a/libraries/render-utils/src/model_lightmap_fade.slf b/libraries/render-utils/src/model_lightmap_fade.slf deleted file mode 100644 index 61568463a7..0000000000 --- a/libraries/render-utils/src/model_lightmap_fade.slf +++ /dev/null @@ -1,59 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Olivier Prat on 06/05/17. -// 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 DeferredBufferWrite.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC)$> -<$declareMaterialLightmap()$> - -<@include Fade.slh@> -<$declareFadeFragment()$> - -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; - -void main(void) { - vec3 fadeEmissive; - FadeObjectParams fadeParams; - <$fetchFadeObjectParams(fadeParams)$> - applyFade(fadeParams, _positionWS.xyz, fadeEmissive); - - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmap)$> - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - packDeferredFragmentLightmap( - normalize(_normalWS), - evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedoTex.a), - albedo, - roughness, - metallic, - lightmap + fadeEmissive); -} diff --git a/libraries/render-utils/src/model_lightmap_normal_map.slf b/libraries/render-utils/src/model_lightmap_normal_map.slf deleted file mode 100644 index 3d961584c2..0000000000 --- a/libraries/render-utils/src/model_lightmap_normal_map.slf +++ /dev/null @@ -1,55 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Samuel Gateau on 11/19/14. -// Copyright 2014 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 DeferredBufferWrite.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC)$> -<$declareMaterialLightmap()$> - -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_TANGENT_WS) in vec3 _tangentWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -void main(void) { - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmap)$> - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - vec3 fragNormal; - <$evalMaterialNormalLOD(_positionES, normalTex, _normalWS, _tangentWS, fragNormal)$> - - packDeferredFragmentLightmap( - normalize(fragNormal), - evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedoTex.a), - albedo, - roughness, - metallic, - lightmap); -} diff --git a/libraries/render-utils/src/model_lightmap_normal_map_fade.slf b/libraries/render-utils/src/model_lightmap_normal_map_fade.slf deleted file mode 100644 index f873847474..0000000000 --- a/libraries/render-utils/src/model_lightmap_normal_map_fade.slf +++ /dev/null @@ -1,64 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Olivier Prat on 06/05/17. -// 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 DeferredBufferWrite.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC)$> -<$declareMaterialLightmap()$> - -<@include Fade.slh@> -<$declareFadeFragment()$> - -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_TANGENT_WS) in vec3 _tangentWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -void main(void) { - vec3 fadeEmissive; - FadeObjectParams fadeParams; - <$fetchFadeObjectParams(fadeParams)$> - applyFade(fadeParams, _positionWS.xyz, fadeEmissive); - - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmap)$> - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - vec3 fragNormal; - <$evalMaterialNormalLOD(_positionES, normalTex, _normalWS, _tangentWS, fragNormal)$> - - packDeferredFragmentLightmap( - normalize(fragNormal), - evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedoTex.a), - albedo, - roughness, - metallic, - lightmap + fadeEmissive); -} diff --git a/libraries/render-utils/src/model_normal_map.slf b/libraries/render-utils/src/model_normal_map.slf deleted file mode 100644 index 695fadbca8..0000000000 --- a/libraries/render-utils/src/model_normal_map.slf +++ /dev/null @@ -1,69 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Andrzej Kapolka on 5/6/14. -// Copyright 2014 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 DeferredBufferWrite.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC, EMISSIVE, OCCLUSION, SCATTERING)$> - -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_TANGENT_WS) in vec3 _tangentWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -void main(void) { - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex, scatteringTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> - - float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardTransparent(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - vec3 emissive = getMaterialEmissive(mat); - <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; - - float occlusion = DEFAULT_OCCLUSION; - <$evalMaterialOcclusion(occlusionTex, matKey, occlusion)$>; - - float scattering = getMaterialScattering(mat); - <$evalMaterialScattering(scatteringTex, scattering, matKey, scattering)$>; - - vec3 fragNormalWS; - <$evalMaterialNormalLOD(_positionES, normalTex, _normalWS, _tangentWS, fragNormalWS)$> - - packDeferredFragment( - normalize(fragNormalWS), - opacity, - albedo, - roughness, - metallic, - emissive, - occlusion, - scattering); -} diff --git a/libraries/render-utils/src/model_normal_map.slv b/libraries/render-utils/src/model_normal_map.slv deleted file mode 100644 index 0fd9a8b582..0000000000 --- a/libraries/render-utils/src/model_normal_map.slv +++ /dev/null @@ -1,45 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Hifi Engine Team. -// Copyright 2013 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 gpu/Inputs.slh@> -<@include gpu/Color.slh@> -<@include gpu/Transform.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<$declareStandardTransform()$> - -<$declareMaterialTexMapArrayBuffer()$> - -layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_TANGENT_WS) out vec3 _tangentWS; -layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; - -void main(void) { - // pass along the color - _color.rgb = color_sRGBToLinear(inColor.rgb); - _color.a = inColor.a; - - // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToWorldAndEyeAndClipPos(cam, obj, inPosition, _positionWS, _positionES, gl_Position)$> - <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normalWS)$> - <$transformModelToWorldDir(cam, obj, inTangent.xyz, _tangentWS)$> - - TexMapArray texMapArray = getTexMapArray(); - <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$> - <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord1, _positionWS, _texCoord01.zw)$> -} diff --git a/libraries/render-utils/src/model_normal_map_fade.slf b/libraries/render-utils/src/model_normal_map_fade.slf deleted file mode 100644 index 07b6f47b55..0000000000 --- a/libraries/render-utils/src/model_normal_map_fade.slf +++ /dev/null @@ -1,78 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Olivier Prat on 06/05/17. -// 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 DeferredBufferWrite.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC, EMISSIVE, OCCLUSION, SCATTERING)$> - -<@include Fade.slh@> -<$declareFadeFragment()$> - -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_TANGENT_WS) in vec3 _tangentWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -void main(void) { - vec3 fadeEmissive; - FadeObjectParams fadeParams; - <$fetchFadeObjectParams(fadeParams)$> - applyFade(fadeParams, _positionWS.xyz, fadeEmissive); - - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex, scatteringTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> - - float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>; - <$discardTransparent(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - vec3 emissive = getMaterialEmissive(mat); - <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; - - float occlusion = DEFAULT_OCCLUSION; - <$evalMaterialOcclusion(occlusionTex, matKey, occlusion)$>; - - float scattering = getMaterialScattering(mat); - <$evalMaterialScattering(scatteringTex, scattering, matKey, scattering)$>; - - vec3 fragNormalWS; - <$evalMaterialNormalLOD(_positionES, normalTex, _normalWS, _tangentWS, fragNormalWS)$> - - packDeferredFragment( - normalize(fragNormalWS), - opacity, - albedo, - roughness, - metallic, - emissive + fadeEmissive, - occlusion, - scattering); -} diff --git a/libraries/render-utils/src/model_shadow.slf b/libraries/render-utils/src/model_shadow.slf deleted file mode 100644 index 6d8dfb7e2a..0000000000 --- a/libraries/render-utils/src/model_shadow.slf +++ /dev/null @@ -1,34 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Andrzej Kapolka on 3/24/14. -// Copyright 2013 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 graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<$declareMaterialTextures(ALBEDO, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL)$> - -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy - -layout(location=0) out vec4 _fragColor; - -void main(void) { - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL)$> - - float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardTransparent(opacity)$>; - - // pass-through to set z-buffer - _fragColor = vec4(1.0, 1.0, 1.0, 0.0); -} diff --git a/libraries/render-utils/src/model_shadow.slv b/libraries/render-utils/src/model_shadow.slv deleted file mode 100644 index d455ea4ade..0000000000 --- a/libraries/render-utils/src/model_shadow.slv +++ /dev/null @@ -1,42 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Hifi Engine Team. -// Copyright 2014 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 gpu/Inputs.slh@> - -<@include gpu/Transform.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> - -<$declareStandardTransform()$> -<$declareMaterialTexMapArrayBuffer()$> - -<@include render-utils/ShaderConstants.h@> - -layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; - -void main(void) { - // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> - <$transformModelToWorldPos(obj, inPosition, _positionWS)$> - - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - _texCoord01 = vec4(0.0, 0.0, 0.0, 0.0); - // If we have an opacity mask than we need the first tex coord - if ((matKey & OPACITY_MASK_MAP_BIT) != 0) { - TexMapArray texMapArray = getTexMapArray(); - <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$> - } -} diff --git a/libraries/render-utils/src/model_shadow_fade.slf b/libraries/render-utils/src/model_shadow_fade.slf deleted file mode 100644 index 1f94d4a0ac..0000000000 --- a/libraries/render-utils/src/model_shadow_fade.slf +++ /dev/null @@ -1,42 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Olivier Prat on 06/05/17. -// 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 graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<$declareMaterialTextures(ALBEDO, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL)$> - -<@include Fade.slh@> -<$declareFadeFragment()$> - -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy - -layout(location=0) out vec4 _fragColor; - -void main(void) { - FadeObjectParams fadeParams; - <$fetchFadeObjectParams(fadeParams)$> - applyFadeClip(fadeParams, _positionWS.xyz); - - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL)$> - - float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardTransparent(opacity)$>; - - // pass-through to set z-buffer - _fragColor = vec4(1.0, 1.0, 1.0, 0.0); -} diff --git a/libraries/render-utils/src/model_translucent.slf b/libraries/render-utils/src/model_translucent.slf deleted file mode 100644 index 72f6b4c187..0000000000 --- a/libraries/render-utils/src/model_translucent.slf +++ /dev/null @@ -1,96 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Sam Gateau on 2/15/2016. -// Copyright 2014 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 DefaultMaterials.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<@include LightLocal.slh@> -<@include DeferredGlobalLight.slh@> - -<$declareEvalGlobalLightingAlphaBlendedWithHaze()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC, EMISSIVE, OCCLUSION)$> - -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -layout(location=0) out vec4 _fragColor; - -void main(void) { - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> - - float opacity = getMaterialOpacity(mat) * _color.a; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardInvisible(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - vec3 fresnel = getFresnelF0(metallic, albedo); - - vec3 emissive = getMaterialEmissive(mat); - <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; - - float occlusion = DEFAULT_OCCLUSION; - <$evalMaterialOcclusion(occlusionTex, matKey, occlusion)$>; - - vec3 fragPositionES = _positionES.xyz; - vec3 fragPositionWS = _positionWS.xyz; - // Lighting is done in world space - vec3 fragNormalWS = normalize(_normalWS); - - TransformCamera cam = getTransformCamera(); - vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS; - vec3 fragToEyeDirWS = normalize(fragToEyeWS); - SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS); - - vec4 localLighting = vec4(0.0); - <$fetchClusterInfo(_positionWS)$>; - if (hasLocalLights(numLights, clusterPos, dims)) { - localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS, - metallic, fresnel, albedo, 0.0, - vec4(0), vec4(0), opacity); - } - - _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze( - cam._viewInverse, - 1.0, - occlusion, - fragPositionES, - fragPositionWS, - albedo, - fresnel, - metallic, - emissive, - surfaceWS, opacity, localLighting.rgb), - opacity); -} diff --git a/libraries/render-utils/src/model_translucent_fade.slf b/libraries/render-utils/src/model_translucent_fade.slf deleted file mode 100644 index 7e170759c4..0000000000 --- a/libraries/render-utils/src/model_translucent_fade.slf +++ /dev/null @@ -1,104 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Olivier Prat on 06/05/17. -// 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 DefaultMaterials.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<@include LightLocal.slh@> -<@include DeferredGlobalLight.slh@> - -<$declareEvalGlobalLightingAlphaBlendedWithHaze()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC, EMISSIVE, OCCLUSION)$> - -<@include Fade.slh@> -<$declareFadeFragment()$> - -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -layout(location=0) out vec4 _fragColor; - -void main(void) { - vec3 fadeEmissive; - FadeObjectParams fadeParams; - <$fetchFadeObjectParams(fadeParams)$> - applyFade(fadeParams, _positionWS.xyz, fadeEmissive); - - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> - - float opacity = getMaterialOpacity(mat) * _color.a; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardTransparent(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - vec3 fresnel = getFresnelF0(metallic, albedo); - - vec3 emissive = getMaterialEmissive(mat); - <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; - - float occlusion = DEFAULT_OCCLUSION; - <$evalMaterialOcclusion(occlusionTex, matKey, occlusion)$>; - - vec3 fragPositionES = _positionES.xyz; - vec3 fragPositionWS = _positionWS.xyz; - // Lighting is done in world space - vec3 fragNormalWS = normalize(_normalWS); - - TransformCamera cam = getTransformCamera(); - vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS; - vec3 fragToEyeDirWS = normalize(fragToEyeWS); - SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS); - - vec4 localLighting = vec4(0.0); - <$fetchClusterInfo(_positionWS)$>; - if (hasLocalLights(numLights, clusterPos, dims)) { - localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS, - metallic, fresnel, albedo, 0.0, - vec4(0), vec4(0), opacity); - } - - _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze( - cam._viewInverse, - 1.0, - occlusion, - fragPositionES, - fragPositionWS, - albedo, - fresnel, - metallic, - emissive + fadeEmissive, - surfaceWS, opacity, localLighting.rgb), - opacity); -} diff --git a/libraries/render-utils/src/model_translucent_normal_map.slf b/libraries/render-utils/src/model_translucent_normal_map.slf deleted file mode 100644 index b3a9127acf..0000000000 --- a/libraries/render-utils/src/model_translucent_normal_map.slf +++ /dev/null @@ -1,98 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Olivier Prat on 23/01/2018. -// Copyright 2018 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 DefaultMaterials.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<@include LightLocal.slh@> -<@include DeferredGlobalLight.slh@> - -<$declareEvalGlobalLightingAlphaBlendedWithHaze()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC, EMISSIVE, OCCLUSION)$> - -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_TANGENT_WS) in vec3 _tangentWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -layout(location=0) out vec4 _fragColor; - -void main(void) { - Material mat = getMaterial(); - int matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> - - float opacity = getMaterialOpacity(mat) * _color.a; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardInvisible(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - vec3 fresnel = getFresnelF0(metallic, albedo); - - vec3 emissive = getMaterialEmissive(mat); - <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; - - float occlusion = DEFAULT_OCCLUSION; - <$evalMaterialOcclusion(occlusionTex, matKey, occlusion)$>; - - vec3 fragPositionES = _positionES.xyz; - vec3 fragPositionWS = _positionWS.xyz; - // Lighting is done in world space - vec3 fragNormalWS; - <$evalMaterialNormalLOD(_positionES, normalTex, _normalWS, _tangentWS, fragNormalWS)$> - - TransformCamera cam = getTransformCamera(); - vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS; - vec3 fragToEyeDirWS = normalize(fragToEyeWS); - SurfaceData surfaceWS = initSurfaceData(roughness, normalize(fragNormalWS), fragToEyeDirWS); - - vec4 localLighting = vec4(0.0); - <$fetchClusterInfo(_positionWS)$>; - if (hasLocalLights(numLights, clusterPos, dims)) { - localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS, - metallic, fresnel, albedo, 0.0, - vec4(0), vec4(0), opacity); - } - - _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze( - cam._viewInverse, - 1.0, - occlusion, - fragPositionES, - fragPositionWS, - albedo, - fresnel, - metallic, - emissive, - surfaceWS, opacity, localLighting.rgb), - opacity); -} diff --git a/libraries/render-utils/src/model_translucent_normal_map_fade.slf b/libraries/render-utils/src/model_translucent_normal_map_fade.slf deleted file mode 100644 index 4c56ebda2e..0000000000 --- a/libraries/render-utils/src/model_translucent_normal_map_fade.slf +++ /dev/null @@ -1,106 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Olivier Prat on 23/01/18. -// Copyright 2018 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 DefaultMaterials.slh@> -<@include graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<@include LightLocal.slh@> -<@include DeferredGlobalLight.slh@> - -<$declareEvalGlobalLightingAlphaBlendedWithHaze()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC, EMISSIVE, OCCLUSION)$> - -<@include Fade.slh@> -<$declareFadeFragment()$> - -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_TANGENT_WS) in vec3 _tangentWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -layout(location=0) out vec4 _fragColor; - -void main(void) { - vec3 fadeEmissive; - FadeObjectParams fadeParams; - <$fetchFadeObjectParams(fadeParams)$> - applyFade(fadeParams, _positionWS.xyz, fadeEmissive); - - Material mat = getMaterial(); - int matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> - - float opacity = getMaterialOpacity(mat) * _color.a; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardInvisible(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - vec3 fresnel = getFresnelF0(metallic, albedo); - - vec3 emissive = getMaterialEmissive(mat); - <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; - - float occlusion = DEFAULT_OCCLUSION; - <$evalMaterialOcclusion(occlusionTex, matKey, occlusion)$>; - - vec3 fragPositionES = _positionES.xyz; - vec3 fragPositionWS = _positionWS.xyz; - // Lighting is done in world space - vec3 fragNormalWS; - <$evalMaterialNormalLOD(_positionES, normalTex, _normalWS, _tangentWS, fragNormalWS)$> - - TransformCamera cam = getTransformCamera(); - vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS; - vec3 fragToEyeDirWS = normalize(fragToEyeWS); - SurfaceData surfaceWS = initSurfaceData(roughness, normalize(fragNormalWS), fragToEyeDirWS); - - vec4 localLighting = vec4(0.0); - <$fetchClusterInfo(_positionWS)$>; - if (hasLocalLights(numLights, clusterPos, dims)) { - localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS, - metallic, fresnel, albedo, 0.0, - vec4(0), vec4(0), opacity); - } - - _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze( - cam._viewInverse, - 1.0, - occlusion, - fragPositionES, - fragPositionWS, - albedo, - fresnel, - metallic, - emissive + fadeEmissive, - surfaceWS, opacity, localLighting.rgb), - opacity); -} diff --git a/libraries/render-utils/src/model_translucent_unlit.slf b/libraries/render-utils/src/model_translucent_unlit.slf deleted file mode 100644 index 37f58d3da9..0000000000 --- a/libraries/render-utils/src/model_translucent_unlit.slf +++ /dev/null @@ -1,42 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Zach Pomerantz on 2/3/2016. -// Copyright 2016 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 graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<@include LightingModel.slh@> - -<$declareMaterialTextures(ALBEDO)$> - -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -layout(location=0) out vec4 _fragColor; - -void main(void) { - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$> - - float opacity = getMaterialOpacity(mat) * _color.a; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardInvisible(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - _fragColor = vec4(albedo * isUnlitEnabled(), opacity); -} diff --git a/libraries/render-utils/src/model_translucent_unlit_fade.slf b/libraries/render-utils/src/model_translucent_unlit_fade.slf deleted file mode 100644 index 04d57b7c47..0000000000 --- a/libraries/render-utils/src/model_translucent_unlit_fade.slf +++ /dev/null @@ -1,52 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Olivier Prat on 06/05/17. -// 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 graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<@include LightingModel.slh@> - -<$declareMaterialTextures(ALBEDO)$> - -<@include Fade.slh@> -<$declareFadeFragment()$> - -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; - -layout(location=0) out vec4 _fragColor; - -void main(void) { - vec3 fadeEmissive; - FadeObjectParams fadeParams; - <$fetchFadeObjectParams(fadeParams)$> - applyFade(fadeParams, _positionWS.xyz, fadeEmissive); - - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$> - - float opacity = getMaterialOpacity(mat) * _color.a; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardInvisible(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - albedo += fadeEmissive; - - _fragColor = vec4(albedo * isUnlitEnabled(), opacity); -} diff --git a/libraries/render-utils/src/model_unlit.slf b/libraries/render-utils/src/model_unlit.slf deleted file mode 100644 index cbac67a72e..0000000000 --- a/libraries/render-utils/src/model_unlit.slf +++ /dev/null @@ -1,45 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Sam Gateau on 5/5/2016. -// Copyright 2016 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 graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<@include DeferredBufferWrite.slh@> -<@include LightingModel.slh@> - -<$declareMaterialTextures(ALBEDO)$> - -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -void main(void) { - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$> - - float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardTransparent(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - - packDeferredFragmentUnlit( - normalize(_normalWS), - opacity, - albedo * isUnlitEnabled()); -} diff --git a/libraries/render-utils/src/model_unlit_fade.slf b/libraries/render-utils/src/model_unlit_fade.slf deleted file mode 100644 index 3097c04c26..0000000000 --- a/libraries/render-utils/src/model_unlit_fade.slf +++ /dev/null @@ -1,55 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// <$_SCRIBE_FILENAME$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Olivier Prat on 06/05/17. -// 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 graphics/Material.slh@> -<@include graphics/MaterialTextures.slh@> -<@include render-utils/ShaderConstants.h@> - -<@include DeferredBufferWrite.slh@> -<@include LightingModel.slh@> - -<@include Fade.slh@> -<$declareFadeFragment()$> - -<$declareMaterialTextures(ALBEDO)$> - -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; - -void main(void) { - vec3 fadeEmissive; - FadeObjectParams fadeParams; - <$fetchFadeObjectParams(fadeParams)$> - applyFade(fadeParams, _positionWS.xyz, fadeEmissive); - - Material mat = getMaterial(); - BITFIELD matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$> - - float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardTransparent(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color.rgb; - albedo += fadeEmissive; - - packDeferredFragmentUnlit( - normalize(_normalWS), - opacity, - albedo * isUnlitEnabled()); -} diff --git a/libraries/render-utils/src/parabola.slf b/libraries/render-utils/src/parabola.slf index ea51d7e3af..f19f82ec59 100644 --- a/libraries/render-utils/src/parabola.slf +++ b/libraries/render-utils/src/parabola.slf @@ -1,5 +1,6 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> +// <$_SCRIBE_FILENAME$> // Generated on <$_SCRIBE_DATE$> // // Created by Sam Gondelman on 7/18/2018 @@ -9,10 +10,22 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include DeferredBufferWrite.slh@> +<@if not HIFI_USE_FORWARD@> + <@include DeferredBufferWrite.slh@> +<@else@> + layout(location=0) out vec4 _fragColor0; +<@endif@> layout(location=0) in vec4 _color; void main(void) { - packDeferredFragmentUnlit(vec3(1.0, 0.0, 0.0), 1.0, _color.rgb); +<@if not HIFI_USE_FORWARD@> + <@if not HIFI_USE_TRANSLUCENT@> + packDeferredFragmentUnlit(vec3(1.0, 0.0, 0.0), 1.0, _color.rgb); + <@else@> + packDeferredFragmentTranslucent(vec3(1.0, 0.0, 0.0), _color.a, _color.rgb, DEFAULT_ROUGHNESS); + <@endif@> +<@else@> + _fragColor0 = _color; +<@endif@> } diff --git a/libraries/render-utils/src/parabola_translucent.slf b/libraries/render-utils/src/parabola_translucent.slf deleted file mode 100644 index 01f4614172..0000000000 --- a/libraries/render-utils/src/parabola_translucent.slf +++ /dev/null @@ -1,18 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// Created by Sam Gondelman on 9/10/2018 -// Copyright 2018 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 DeferredBufferWrite.slh@> - -layout(location=0) in vec4 _color; - -void main(void) { - packDeferredFragmentTranslucent(vec3(1.0, 0.0, 0.0), _color.a, _color.rgb, DEFAULT_ROUGHNESS); -} diff --git a/libraries/render-utils/src/render-utils/ShaderConstants.h b/libraries/render-utils/src/render-utils/ShaderConstants.h index 76c8dd4981..19eb4dd249 100644 --- a/libraries/render-utils/src/render-utils/ShaderConstants.h +++ b/libraries/render-utils/src/render-utils/ShaderConstants.h @@ -68,7 +68,6 @@ #define RENDER_UTILS_BUFFER_LIGHT_CLUSTER_CONTENT 12 // Haze -#define RENDER_UTILS_BUFFER_HAZE_PARAMS 7 #define RENDER_UTILS_TEXTURE_HAZE_COLOR 0 #define RENDER_UTILS_TEXTURE_HAZE_LINEAR_DEPTH 1 @@ -143,7 +142,6 @@ enum Buffer { DeferredFrameTransform = RENDER_UTILS_BUFFER_DEFERRED_FRAME_TRANSFORM, LightModel = RENDER_UTILS_BUFFER_LIGHT_MODEL, AmbientLight = RENDER_UTILS_BUFFER_AMBIENT_LIGHT, - HazeParams = RENDER_UTILS_BUFFER_HAZE_PARAMS, FadeParameters = RENDER_UTILS_BUFFER_FADE_PARAMS, FadeObjectParameters = RENDER_UTILS_BUFFER_FADE_OBJECT_PARAMS, LightClusterFrustumGrid = RENDER_UTILS_BUFFER_LIGHT_CLUSTER_FRUSTUM_GRID, diff --git a/libraries/render-utils/src/render-utils/deformed_model.slp b/libraries/render-utils/src/render-utils/deformed_model.slp deleted file mode 100644 index 9db8938e86..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model -FRAGMENT model diff --git a/libraries/render-utils/src/render-utils/deformed_model_dq.slp b/libraries/render-utils/src/render-utils/deformed_model_dq.slp deleted file mode 100644 index ec950ac784..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_dq.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_dq -FRAGMENT model diff --git a/libraries/render-utils/src/render-utils/deformed_model_fade.slp b/libraries/render-utils/src/render-utils/deformed_model_fade.slp deleted file mode 100644 index 5818e5e3af..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_fade.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model -FRAGMENT model_fade diff --git a/libraries/render-utils/src/render-utils/deformed_model_fade_dq.slp b/libraries/render-utils/src/render-utils/deformed_model_fade_dq.slp deleted file mode 100644 index 9047bc1286..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_fade_dq.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_dq -FRAGMENT model_fade diff --git a/libraries/render-utils/src/render-utils/deformed_model_normal_map.slp b/libraries/render-utils/src/render-utils/deformed_model_normal_map.slp deleted file mode 100644 index ad460652ad..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_normal_map.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_normal_map -FRAGMENT model_normal_map diff --git a/libraries/render-utils/src/render-utils/deformed_model_normal_map_dq.slp b/libraries/render-utils/src/render-utils/deformed_model_normal_map_dq.slp deleted file mode 100644 index 44d5cd5272..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_normal_map_dq.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_normal_map_dq -FRAGMENT model_normal_map diff --git a/libraries/render-utils/src/render-utils/deformed_model_normal_map_fade.slp b/libraries/render-utils/src/render-utils/deformed_model_normal_map_fade.slp deleted file mode 100644 index 99aab59169..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_normal_map_fade.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_normal_map -FRAGMENT model_normal_map_fade diff --git a/libraries/render-utils/src/render-utils/deformed_model_normal_map_fade_dq.slp b/libraries/render-utils/src/render-utils/deformed_model_normal_map_fade_dq.slp deleted file mode 100644 index 0ee002b6a1..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_normal_map_fade_dq.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_normal_map_dq -FRAGMENT model_normal_map_fade diff --git a/libraries/render-utils/src/render-utils/deformed_model_normal_map_translucent.slp b/libraries/render-utils/src/render-utils/deformed_model_normal_map_translucent.slp deleted file mode 100644 index f2e2b2e4da..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_normal_map_translucent.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_normal_map -FRAGMENT model_translucent_normal_map diff --git a/libraries/render-utils/src/render-utils/deformed_model_normal_map_translucent_dq.slp b/libraries/render-utils/src/render-utils/deformed_model_normal_map_translucent_dq.slp deleted file mode 100644 index 577a6c1616..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_normal_map_translucent_dq.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_normal_map_dq -FRAGMENT model_translucent_normal_map diff --git a/libraries/render-utils/src/render-utils/deformed_model_normal_map_translucent_fade.slp b/libraries/render-utils/src/render-utils/deformed_model_normal_map_translucent_fade.slp deleted file mode 100644 index de9591b45f..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_normal_map_translucent_fade.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_normal_map -FRAGMENT model_translucent_normal_map_fade diff --git a/libraries/render-utils/src/render-utils/deformed_model_normal_map_translucent_fade_dq.slp b/libraries/render-utils/src/render-utils/deformed_model_normal_map_translucent_fade_dq.slp deleted file mode 100644 index 3f624f7bf7..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_normal_map_translucent_fade_dq.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_normal_map_dq -FRAGMENT model_translucent_normal_map_fade diff --git a/libraries/render-utils/src/render-utils/deformed_model_shadow.slp b/libraries/render-utils/src/render-utils/deformed_model_shadow.slp deleted file mode 100644 index c8718dff09..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_shadow.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_shadow -FRAGMENT model_shadow diff --git a/libraries/render-utils/src/render-utils/deformed_model_shadow_dq.slp b/libraries/render-utils/src/render-utils/deformed_model_shadow_dq.slp deleted file mode 100644 index b0f1449234..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_shadow_dq.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_shadow_dq -FRAGMENT model_shadow diff --git a/libraries/render-utils/src/render-utils/deformed_model_shadow_fade.slp b/libraries/render-utils/src/render-utils/deformed_model_shadow_fade.slp deleted file mode 100644 index 1063134d96..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_shadow_fade.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_shadow -FRAGMENT model_shadow_fade diff --git a/libraries/render-utils/src/render-utils/deformed_model_shadow_fade_dq.slp b/libraries/render-utils/src/render-utils/deformed_model_shadow_fade_dq.slp deleted file mode 100644 index 25c99c75d1..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_shadow_fade_dq.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_shadow_dq -FRAGMENT model_shadow_fade diff --git a/libraries/render-utils/src/render-utils/deformed_model_translucent.slp b/libraries/render-utils/src/render-utils/deformed_model_translucent.slp deleted file mode 100644 index 798fec9a5b..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_translucent.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model -FRAGMENT model_translucent diff --git a/libraries/render-utils/src/render-utils/deformed_model_translucent_dq.slp b/libraries/render-utils/src/render-utils/deformed_model_translucent_dq.slp deleted file mode 100644 index 8a0b70cfcf..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_translucent_dq.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_dq -FRAGMENT model_translucent diff --git a/libraries/render-utils/src/render-utils/deformed_model_translucent_fade.slp b/libraries/render-utils/src/render-utils/deformed_model_translucent_fade.slp deleted file mode 100644 index 68eef3624d..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_translucent_fade.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model -FRAGMENT model_translucent_fade diff --git a/libraries/render-utils/src/render-utils/deformed_model_translucent_fade_dq.slp b/libraries/render-utils/src/render-utils/deformed_model_translucent_fade_dq.slp deleted file mode 100644 index 4ce321fa78..0000000000 --- a/libraries/render-utils/src/render-utils/deformed_model_translucent_fade_dq.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_dq -FRAGMENT model_translucent_fade diff --git a/libraries/render-utils/src/render-utils/forward_deformed_model.slp b/libraries/render-utils/src/render-utils/forward_deformed_model.slp deleted file mode 100644 index 3b7c49705b..0000000000 --- a/libraries/render-utils/src/render-utils/forward_deformed_model.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model -FRAGMENT forward_model diff --git a/libraries/render-utils/src/render-utils/forward_deformed_model_dq.slp b/libraries/render-utils/src/render-utils/forward_deformed_model_dq.slp deleted file mode 100644 index 45d886529a..0000000000 --- a/libraries/render-utils/src/render-utils/forward_deformed_model_dq.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_dq -FRAGMENT forward_model diff --git a/libraries/render-utils/src/render-utils/forward_deformed_model_normal_map.slp b/libraries/render-utils/src/render-utils/forward_deformed_model_normal_map.slp deleted file mode 100644 index 539ca61193..0000000000 --- a/libraries/render-utils/src/render-utils/forward_deformed_model_normal_map.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_normal_map -FRAGMENT forward_model_normal_map diff --git a/libraries/render-utils/src/render-utils/forward_deformed_model_normal_map_dq.slp b/libraries/render-utils/src/render-utils/forward_deformed_model_normal_map_dq.slp deleted file mode 100644 index c663b671fe..0000000000 --- a/libraries/render-utils/src/render-utils/forward_deformed_model_normal_map_dq.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_normal_map_dq -FRAGMENT forward_model_normal_map diff --git a/libraries/render-utils/src/render-utils/forward_deformed_translucent.slp b/libraries/render-utils/src/render-utils/forward_deformed_translucent.slp deleted file mode 100644 index 605499ebc3..0000000000 --- a/libraries/render-utils/src/render-utils/forward_deformed_translucent.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model -FRAGMENT forward_model_translucent diff --git a/libraries/render-utils/src/render-utils/forward_deformed_translucent_dq.slp b/libraries/render-utils/src/render-utils/forward_deformed_translucent_dq.slp deleted file mode 100644 index cd20657b01..0000000000 --- a/libraries/render-utils/src/render-utils/forward_deformed_translucent_dq.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_dq -FRAGMENT forward_model_translucent diff --git a/libraries/render-utils/src/render-utils/forward_deformed_translucent_normal_map.slp b/libraries/render-utils/src/render-utils/forward_deformed_translucent_normal_map.slp deleted file mode 100644 index 85d08c1943..0000000000 --- a/libraries/render-utils/src/render-utils/forward_deformed_translucent_normal_map.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_normal_map -FRAGMENT forward_model_translucent diff --git a/libraries/render-utils/src/render-utils/forward_deformed_translucent_normal_map_dq.slp b/libraries/render-utils/src/render-utils/forward_deformed_translucent_normal_map_dq.slp deleted file mode 100644 index 2f13b16a5b..0000000000 --- a/libraries/render-utils/src/render-utils/forward_deformed_translucent_normal_map_dq.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX deformed_model_normal_map_dq -FRAGMENT forward_model_translucent diff --git a/libraries/render-utils/src/render-utils/forward_grid.slp b/libraries/render-utils/src/render-utils/forward_grid.slp deleted file mode 100644 index c81b208f63..0000000000 --- a/libraries/render-utils/src/render-utils/forward_grid.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX standardTransformPNTC diff --git a/libraries/render-utils/src/render-utils/forward_grid_translucent.slp b/libraries/render-utils/src/render-utils/forward_grid_translucent.slp deleted file mode 100644 index c81b208f63..0000000000 --- a/libraries/render-utils/src/render-utils/forward_grid_translucent.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX standardTransformPNTC diff --git a/libraries/render-utils/src/render-utils/forward_model.slp b/libraries/render-utils/src/render-utils/forward_model.slp deleted file mode 100644 index 81ac672062..0000000000 --- a/libraries/render-utils/src/render-utils/forward_model.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model diff --git a/libraries/render-utils/src/render-utils/forward_model_lightmap.slp b/libraries/render-utils/src/render-utils/forward_model_lightmap.slp deleted file mode 100644 index 81ac672062..0000000000 --- a/libraries/render-utils/src/render-utils/forward_model_lightmap.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model diff --git a/libraries/render-utils/src/render-utils/forward_model_normal_map.slp b/libraries/render-utils/src/render-utils/forward_model_normal_map.slp deleted file mode 100644 index c50be6285b..0000000000 --- a/libraries/render-utils/src/render-utils/forward_model_normal_map.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model_normal_map diff --git a/libraries/render-utils/src/render-utils/forward_model_normal_map_lightmap.slp b/libraries/render-utils/src/render-utils/forward_model_normal_map_lightmap.slp deleted file mode 100644 index c50be6285b..0000000000 --- a/libraries/render-utils/src/render-utils/forward_model_normal_map_lightmap.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model_normal_map diff --git a/libraries/render-utils/src/render-utils/forward_model_normal_map_translucent.slp b/libraries/render-utils/src/render-utils/forward_model_normal_map_translucent.slp deleted file mode 100644 index 0979918b98..0000000000 --- a/libraries/render-utils/src/render-utils/forward_model_normal_map_translucent.slp +++ /dev/null @@ -1,2 +0,0 @@ -VERTEX model_normal_map -FRAGMENT forward_model_translucent diff --git a/libraries/render-utils/src/render-utils/forward_model_translucent.slp b/libraries/render-utils/src/render-utils/forward_model_translucent.slp deleted file mode 100644 index 81ac672062..0000000000 --- a/libraries/render-utils/src/render-utils/forward_model_translucent.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model diff --git a/libraries/render-utils/src/render-utils/forward_model_unlit.slp b/libraries/render-utils/src/render-utils/forward_model_unlit.slp deleted file mode 100644 index 81ac672062..0000000000 --- a/libraries/render-utils/src/render-utils/forward_model_unlit.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model diff --git a/libraries/render-utils/src/render-utils/forward_parabola.slp b/libraries/render-utils/src/render-utils/forward_parabola.slp deleted file mode 100644 index ab3f1d4126..0000000000 --- a/libraries/render-utils/src/render-utils/forward_parabola.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX parabola diff --git a/libraries/render-utils/src/render-utils/forward_sdf_text3D.slp b/libraries/render-utils/src/render-utils/forward_sdf_text3D.slp deleted file mode 100644 index 3eea3a0da0..0000000000 --- a/libraries/render-utils/src/render-utils/forward_sdf_text3D.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX sdf_text3D diff --git a/libraries/render-utils/src/render-utils/forward_simple_textured.slp b/libraries/render-utils/src/render-utils/forward_simple_textured.slp deleted file mode 100644 index 10e6b388c4..0000000000 --- a/libraries/render-utils/src/render-utils/forward_simple_textured.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX simple diff --git a/libraries/render-utils/src/render-utils/forward_simple_textured_transparent.slp b/libraries/render-utils/src/render-utils/forward_simple_textured_transparent.slp deleted file mode 100644 index 10e6b388c4..0000000000 --- a/libraries/render-utils/src/render-utils/forward_simple_textured_transparent.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX simple diff --git a/libraries/render-utils/src/render-utils/forward_simple_textured_unlit.slp b/libraries/render-utils/src/render-utils/forward_simple_textured_unlit.slp deleted file mode 100644 index 10e6b388c4..0000000000 --- a/libraries/render-utils/src/render-utils/forward_simple_textured_unlit.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX simple diff --git a/libraries/render-utils/src/render-utils/glowLine.slp b/libraries/render-utils/src/render-utils/glowLine.slp deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/libraries/render-utils/src/render-utils/grid.slp b/libraries/render-utils/src/render-utils/grid.slp index c81b208f63..5cf10ff674 100644 --- a/libraries/render-utils/src/render-utils/grid.slp +++ b/libraries/render-utils/src/render-utils/grid.slp @@ -1 +1,2 @@ VERTEX standardTransformPNTC +DEFINES translucent:f forward:f \ No newline at end of file diff --git a/libraries/render-utils/src/render-utils/grid_translucent.slp b/libraries/render-utils/src/render-utils/grid_translucent.slp deleted file mode 100644 index c81b208f63..0000000000 --- a/libraries/render-utils/src/render-utils/grid_translucent.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX standardTransformPNTC diff --git a/libraries/render-utils/src/render-utils/model.slp b/libraries/render-utils/src/render-utils/model.slp index e69de29bb2..b63ec898eb 100644 --- a/libraries/render-utils/src/render-utils/model.slp +++ b/libraries/render-utils/src/render-utils/model.slp @@ -0,0 +1 @@ +DEFINES (normalmap translucent:f unlit:f/lightmap:f)/shadow fade:f/forward:f deformed:v/deformeddq:v \ No newline at end of file diff --git a/libraries/render-utils/src/render-utils/model_fade.slp b/libraries/render-utils/src/render-utils/model_fade.slp deleted file mode 100644 index ea0b2cf566..0000000000 --- a/libraries/render-utils/src/render-utils/model_fade.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model \ No newline at end of file diff --git a/libraries/render-utils/src/render-utils/model_lightmap.slp b/libraries/render-utils/src/render-utils/model_lightmap.slp deleted file mode 100644 index ea0b2cf566..0000000000 --- a/libraries/render-utils/src/render-utils/model_lightmap.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model \ No newline at end of file diff --git a/libraries/render-utils/src/render-utils/model_lightmap_fade.slp b/libraries/render-utils/src/render-utils/model_lightmap_fade.slp deleted file mode 100644 index ea0b2cf566..0000000000 --- a/libraries/render-utils/src/render-utils/model_lightmap_fade.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model \ No newline at end of file diff --git a/libraries/render-utils/src/render-utils/model_lightmap_normal_map.slp b/libraries/render-utils/src/render-utils/model_lightmap_normal_map.slp deleted file mode 100644 index c50be6285b..0000000000 --- a/libraries/render-utils/src/render-utils/model_lightmap_normal_map.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model_normal_map diff --git a/libraries/render-utils/src/render-utils/model_lightmap_normal_map_fade.slp b/libraries/render-utils/src/render-utils/model_lightmap_normal_map_fade.slp deleted file mode 100644 index 659899f9f8..0000000000 --- a/libraries/render-utils/src/render-utils/model_lightmap_normal_map_fade.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model_normal_map \ No newline at end of file diff --git a/libraries/render-utils/src/render-utils/model_normal_map.slp b/libraries/render-utils/src/render-utils/model_normal_map.slp deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/libraries/render-utils/src/render-utils/model_normal_map_fade.slp b/libraries/render-utils/src/render-utils/model_normal_map_fade.slp deleted file mode 100644 index 659899f9f8..0000000000 --- a/libraries/render-utils/src/render-utils/model_normal_map_fade.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model_normal_map \ No newline at end of file diff --git a/libraries/render-utils/src/render-utils/model_shadow.slp b/libraries/render-utils/src/render-utils/model_shadow.slp deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/libraries/render-utils/src/render-utils/model_shadow_fade.slp b/libraries/render-utils/src/render-utils/model_shadow_fade.slp deleted file mode 100644 index f43521cba6..0000000000 --- a/libraries/render-utils/src/render-utils/model_shadow_fade.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model_shadow \ No newline at end of file diff --git a/libraries/render-utils/src/render-utils/model_translucent.slp b/libraries/render-utils/src/render-utils/model_translucent.slp deleted file mode 100644 index ea0b2cf566..0000000000 --- a/libraries/render-utils/src/render-utils/model_translucent.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model \ No newline at end of file diff --git a/libraries/render-utils/src/render-utils/model_translucent_fade.slp b/libraries/render-utils/src/render-utils/model_translucent_fade.slp deleted file mode 100644 index 81ac672062..0000000000 --- a/libraries/render-utils/src/render-utils/model_translucent_fade.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model diff --git a/libraries/render-utils/src/render-utils/model_translucent_normal_map.slp b/libraries/render-utils/src/render-utils/model_translucent_normal_map.slp deleted file mode 100644 index 659899f9f8..0000000000 --- a/libraries/render-utils/src/render-utils/model_translucent_normal_map.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model_normal_map \ No newline at end of file diff --git a/libraries/render-utils/src/render-utils/model_translucent_normal_map_fade.slp b/libraries/render-utils/src/render-utils/model_translucent_normal_map_fade.slp deleted file mode 100644 index c50be6285b..0000000000 --- a/libraries/render-utils/src/render-utils/model_translucent_normal_map_fade.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model_normal_map diff --git a/libraries/render-utils/src/render-utils/model_translucent_unlit.slp b/libraries/render-utils/src/render-utils/model_translucent_unlit.slp deleted file mode 100644 index 81ac672062..0000000000 --- a/libraries/render-utils/src/render-utils/model_translucent_unlit.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model diff --git a/libraries/render-utils/src/render-utils/model_translucent_unlit_fade.slp b/libraries/render-utils/src/render-utils/model_translucent_unlit_fade.slp deleted file mode 100644 index 81ac672062..0000000000 --- a/libraries/render-utils/src/render-utils/model_translucent_unlit_fade.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model diff --git a/libraries/render-utils/src/render-utils/model_unlit.slp b/libraries/render-utils/src/render-utils/model_unlit.slp deleted file mode 100644 index 81ac672062..0000000000 --- a/libraries/render-utils/src/render-utils/model_unlit.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model diff --git a/libraries/render-utils/src/render-utils/model_unlit_fade.slp b/libraries/render-utils/src/render-utils/model_unlit_fade.slp deleted file mode 100644 index 81ac672062..0000000000 --- a/libraries/render-utils/src/render-utils/model_unlit_fade.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX model diff --git a/libraries/render-utils/src/render-utils/parabola.slp b/libraries/render-utils/src/render-utils/parabola.slp index e69de29bb2..e9942be5cd 100644 --- a/libraries/render-utils/src/render-utils/parabola.slp +++ b/libraries/render-utils/src/render-utils/parabola.slp @@ -0,0 +1 @@ +DEFINES translucent:f/forward:f \ No newline at end of file diff --git a/libraries/render-utils/src/render-utils/parabola_translucent.slp b/libraries/render-utils/src/render-utils/parabola_translucent.slp deleted file mode 100644 index ab3f1d4126..0000000000 --- a/libraries/render-utils/src/render-utils/parabola_translucent.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX parabola diff --git a/libraries/render-utils/src/render-utils/sdf_text3D.slp b/libraries/render-utils/src/render-utils/sdf_text3D.slp index e69de29bb2..118135d099 100644 --- a/libraries/render-utils/src/render-utils/sdf_text3D.slp +++ b/libraries/render-utils/src/render-utils/sdf_text3D.slp @@ -0,0 +1 @@ +DEFINES (translucent unlit:f)/forward \ No newline at end of file diff --git a/libraries/render-utils/src/render-utils/sdf_text3D_transparent.slp b/libraries/render-utils/src/render-utils/sdf_text3D_transparent.slp deleted file mode 100644 index 3eea3a0da0..0000000000 --- a/libraries/render-utils/src/render-utils/sdf_text3D_transparent.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX sdf_text3D diff --git a/libraries/render-utils/src/render-utils/simple.slp b/libraries/render-utils/src/render-utils/simple.slp index e69de29bb2..5fc7789a21 100644 --- a/libraries/render-utils/src/render-utils/simple.slp +++ b/libraries/render-utils/src/render-utils/simple.slp @@ -0,0 +1 @@ +DEFINES translucent unlit fade/forward \ No newline at end of file diff --git a/libraries/render-utils/src/render-utils/simple_opaque_web_browser.slp b/libraries/render-utils/src/render-utils/simple_opaque_web_browser.slp deleted file mode 100644 index 10e6b388c4..0000000000 --- a/libraries/render-utils/src/render-utils/simple_opaque_web_browser.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX simple diff --git a/libraries/render-utils/src/render-utils/simple_procedural.slp b/libraries/render-utils/src/render-utils/simple_procedural.slp new file mode 100644 index 0000000000..219062d50c --- /dev/null +++ b/libraries/render-utils/src/render-utils/simple_procedural.slp @@ -0,0 +1 @@ +DEFINES translucent:f deformed:v/deformeddq:v \ No newline at end of file diff --git a/libraries/render-utils/src/render-utils/simple_textured.slp b/libraries/render-utils/src/render-utils/simple_textured.slp deleted file mode 100644 index 10e6b388c4..0000000000 --- a/libraries/render-utils/src/render-utils/simple_textured.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX simple diff --git a/libraries/render-utils/src/render-utils/simple_textured_fade.slp b/libraries/render-utils/src/render-utils/simple_textured_fade.slp deleted file mode 100644 index 9be0f525ad..0000000000 --- a/libraries/render-utils/src/render-utils/simple_textured_fade.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX simple_fade diff --git a/libraries/render-utils/src/render-utils/simple_textured_unlit.slp b/libraries/render-utils/src/render-utils/simple_textured_unlit.slp deleted file mode 100644 index 10e6b388c4..0000000000 --- a/libraries/render-utils/src/render-utils/simple_textured_unlit.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX simple diff --git a/libraries/render-utils/src/render-utils/simple_textured_unlit_fade.slp b/libraries/render-utils/src/render-utils/simple_textured_unlit_fade.slp deleted file mode 100644 index 9be0f525ad..0000000000 --- a/libraries/render-utils/src/render-utils/simple_textured_unlit_fade.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX simple_fade diff --git a/libraries/render-utils/src/render-utils/simple_transparent.slp b/libraries/render-utils/src/render-utils/simple_transparent.slp deleted file mode 100644 index 10e6b388c4..0000000000 --- a/libraries/render-utils/src/render-utils/simple_transparent.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX simple diff --git a/libraries/render-utils/src/render-utils/simple_transparent_textured.slp b/libraries/render-utils/src/render-utils/simple_transparent_textured.slp deleted file mode 100644 index 10e6b388c4..0000000000 --- a/libraries/render-utils/src/render-utils/simple_transparent_textured.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX simple diff --git a/libraries/render-utils/src/render-utils/simple_transparent_textured_fade.slp b/libraries/render-utils/src/render-utils/simple_transparent_textured_fade.slp deleted file mode 100644 index 9be0f525ad..0000000000 --- a/libraries/render-utils/src/render-utils/simple_transparent_textured_fade.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX simple_fade diff --git a/libraries/render-utils/src/render-utils/simple_transparent_textured_unlit.slp b/libraries/render-utils/src/render-utils/simple_transparent_textured_unlit.slp deleted file mode 100644 index 10e6b388c4..0000000000 --- a/libraries/render-utils/src/render-utils/simple_transparent_textured_unlit.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX simple diff --git a/libraries/render-utils/src/render-utils/simple_transparent_textured_unlit_fade.slp b/libraries/render-utils/src/render-utils/simple_transparent_textured_unlit_fade.slp deleted file mode 100644 index 9be0f525ad..0000000000 --- a/libraries/render-utils/src/render-utils/simple_transparent_textured_unlit_fade.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX simple_fade diff --git a/libraries/render-utils/src/render-utils/simple_transparent_web_browser.slp b/libraries/render-utils/src/render-utils/simple_transparent_web_browser.slp deleted file mode 100644 index 10e6b388c4..0000000000 --- a/libraries/render-utils/src/render-utils/simple_transparent_web_browser.slp +++ /dev/null @@ -1 +0,0 @@ -VERTEX simple diff --git a/libraries/render-utils/src/render-utils/web_browser.slp b/libraries/render-utils/src/render-utils/web_browser.slp new file mode 100644 index 0000000000..e283f4edcb --- /dev/null +++ b/libraries/render-utils/src/render-utils/web_browser.slp @@ -0,0 +1 @@ +DEFINES forward \ No newline at end of file diff --git a/libraries/render-utils/src/sdf_text3D.slf b/libraries/render-utils/src/sdf_text3D.slf index 91c73e9eec..ac064e5c8f 100644 --- a/libraries/render-utils/src/sdf_text3D.slf +++ b/libraries/render-utils/src/sdf_text3D.slf @@ -1,8 +1,7 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> +// <$_SCRIBE_FILENAME$> // Generated on <$_SCRIBE_DATE$> -// sdf_text3D.frag -// fragment shader // // Created by Bradley Austin Davis on 2015-02-04 // Based on fragment shader code from @@ -10,12 +9,32 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -<@include DeferredBufferWrite.slh@> +<@if HIFI_USE_TRANSLUCENT or HIFI_USE_FORWARD@> + <@include DefaultMaterials.slh@> + + <@include GlobalLight.slh@> + <@if HIFI_USE_TRANSLUCENT@> + <$declareEvalGlobalLightingAlphaBlended()$> + <@else@> + <$declareEvalSkyboxGlobalColor(_SCRIBE_NULL, HIFI_USE_FORWARD)$> + <@endif@> + + <@include gpu/Transform.slh@> + <$declareStandardCameraTransform()$> + + layout(location=0) out vec4 _fragColor0; +<@else@> + <@include DeferredBufferWrite.slh@> +<@endif@> + <@include render-utils/ShaderConstants.h@> <@include sdf_text3D.slh@> <$declareEvalSDFSuperSampled()$> +<@if HIFI_USE_TRANSLUCENT or HIFI_USE_FORWARD@> + layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; +<@endif@> layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; @@ -23,15 +42,65 @@ layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; #define _texCoord1 _texCoord01.zw void main() { - float a = evalSDFSuperSampled(_texCoord0); + float alpha = evalSDFSuperSampled(_texCoord0); - packDeferredFragment( - normalize(_normalWS), - a, - _color.rgb, - DEFAULT_ROUGHNESS, - DEFAULT_METALLIC, - DEFAULT_EMISSIVE, - DEFAULT_OCCLUSION, - DEFAULT_SCATTERING); -} \ No newline at end of file +<@if HIFI_USE_TRANSLUCENT or HIFI_USE_FORWARD@> + alpha *= _color.a; + if (alpha <= 0.0) { + discard; + } +<@endif@> + +<@if HIFI_USE_UNLIT@> + <@if HIFI_USE_TRANSLUCENT or HIFI_USE_FORWARD@> + _fragColor0 = vec4(_color.rgb * isUnlitEnabled(), alpha); + <@else@> + packDeferredFragmentUnlit( + normalize(_normalWS), + alpha, + _color.rgb); + <@endif@> +<@else@> + <@if HIFI_USE_TRANSLUCENT or HIFI_USE_FORWARD@> + TransformCamera cam = getTransformCamera(); + vec3 fragPosition = _positionES.xyz; + + <@if HIFI_USE_TRANSLUCENT@> + _fragColor0 = vec4(evalGlobalLightingAlphaBlended( + cam._viewInverse, + 1.0, + DEFAULT_OCCLUSION, + fragPosition, + normalize(_normalWS), + _color.rgb, + DEFAULT_FRESNEL, + DEFAULT_METALLIC, + DEFAULT_EMISSIVE, + DEFAULT_ROUGHNESS, alpha), + alpha); + <@else@> + _fragColor0 = vec4(evalSkyboxGlobalColor( + cam._viewInverse, + 1.0, + DEFAULT_OCCLUSION, + fragPosition, + normalize(_normalWS), + _color.rgb, + DEFAULT_FRESNEL, + DEFAULT_METALLIC, + DEFAULT_ROUGHNESS), + alpha); + <@endif@> + <@else@> + packDeferredFragment( + normalize(_normalWS), + alpha, + _color.rgb, + DEFAULT_ROUGHNESS, + DEFAULT_METALLIC, + DEFAULT_EMISSIVE, + DEFAULT_OCCLUSION, + DEFAULT_SCATTERING); + <@endif@> +<@endif@> +} diff --git a/libraries/render-utils/src/sdf_text3D.slv b/libraries/render-utils/src/sdf_text3D.slv index 274e09e6ad..731cbc2cad 100644 --- a/libraries/render-utils/src/sdf_text3D.slv +++ b/libraries/render-utils/src/sdf_text3D.slv @@ -19,20 +19,25 @@ <@include sdf_text3D.slh@> -// the interpolated normal -layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; +<@if HIFI_USE_TRANSLUCENT or HIFI_USE_FORWARD@> + layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; +<@endif@> layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; void main() { - _texCoord01.xy = inTexCoord0.xy; + _texCoord01 = vec4(inTexCoord0.st, 0.0, 0.0); _color = color_sRGBAToLinear(params.color); - - // standard transform + TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); +<@if HIFI_USE_TRANSLUCENT or HIFI_USE_FORWARD@> <$transformModelToEyeAndClipPos(cam, obj, inPosition, _positionES, gl_Position)$> +<@else@> + <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> +<@endif@> + const vec3 normal = vec3(0, 0, 1); <$transformModelToWorldDir(cam, obj, normal, _normalWS)$> } \ No newline at end of file diff --git a/libraries/render-utils/src/sdf_text3D_transparent.slf b/libraries/render-utils/src/sdf_text3D_transparent.slf deleted file mode 100644 index c4a80091de..0000000000 --- a/libraries/render-utils/src/sdf_text3D_transparent.slf +++ /dev/null @@ -1,58 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// sdf_text3D_transparent.frag -// fragment shader -// -// Created by Bradley Austin Davis on 2015-02-04 -// Based on fragment shader code from -// https://github.com/paulhoux/Cinder-Samples/blob/master/TextRendering/include/text/Text.cpp -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - -<@include DefaultMaterials.slh@> - -<@include ForwardGlobalLight.slh@> -<$declareEvalGlobalLightingAlphaBlended()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -<@include render-utils/ShaderConstants.h@> - -<@include sdf_text3D.slh@> -<$declareEvalSDFSuperSampled()$> - -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw - -layout(location=0) out vec4 _fragColor0; - -void main() { - float a = evalSDFSuperSampled(_texCoord0); - - float alpha = a * _color.a; - if (alpha <= 0.0) { - discard; - } - - TransformCamera cam = getTransformCamera(); - vec3 fragPosition = _positionES.xyz; - - _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze( - cam._viewInverse, - 1.0, - DEFAULT_OCCLUSION, - fragPosition, - normalize(_normalWS), - _color.rgb, - DEFAULT_FRESNEL, - DEFAULT_METALLIC, - DEFAULT_EMISSIVE, - DEFAULT_ROUGHNESS, alpha), - alpha); -} \ No newline at end of file diff --git a/libraries/render-utils/src/simple.slf b/libraries/render-utils/src/simple.slf index 469c0976aa..9760216682 100644 --- a/libraries/render-utils/src/simple.slf +++ b/libraries/render-utils/src/simple.slf @@ -1,10 +1,8 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> +// <$_SCRIBE_FILENAME$> // Generated on <$_SCRIBE_DATE$> // -// simple.frag -// fragment shader -// // Created by Andrzej Kapolka on 9/15/14. // Copyright 2014 High Fidelity, Inc. // @@ -12,133 +10,144 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include DeferredBufferWrite.slh@> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - +<@include gpu/Color.slh@> +<@include DefaultMaterials.slh@> <@include render-utils/ShaderConstants.h@> -// the interpolated normal +<@if HIFI_USE_FORWARD or HIFI_USE_TRANSLUCENT@> + <@if not HIFI_USE_UNLIT@> + <@include gpu/Transform.slh@> + <$declareStandardCameraTransform()$> + <@else@> + <@include LightingModel.slh@> +<@endif@> + + layout(location=0) out vec4 _fragColor0; +<@endif@> + +<@if not HIFI_USE_UNLIT@> + <@if HIFI_USE_TRANSLUCENT@> + <@include GlobalLight.slh@> + <$declareEvalGlobalLightingAlphaBlended()$> + <@elif HIFI_USE_FORWARD@> + <@include GlobalLight.slh@> + <$declareEvalSkyboxGlobalColor(_SCRIBE_NULL, HIFI_USE_FORWARD)$> + <@else@> + <@include DeferredBufferWrite.slh@> + <@endif@> +<@else@> + <@if not HIFI_USE_FORWARD@> + <@if not HIFI_USE_TRANSLUCENT@> + <@include DeferredBufferWrite.slh@> + <@endif@> + <@endif@> +<@endif@> + +<@if HIFI_USE_FADE@> + <@include Fade.slh@> + <$declareFadeFragmentInstanced()$> +<@endif@> + +<@if not HIFI_USE_UNLIT@> + <@if HIFI_USE_FORWARD or HIFI_USE_TRANSLUCENT@> + layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; + <@endif@> +<@endif@> +<@if HIFI_USE_FADE@> + layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; +<@endif@> layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_NORMAL_MS) in vec3 _normalMS; layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; #define _texCoord0 _texCoord01.xy #define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_POSITION_MS) in vec4 _positionMS; -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -// For retro-compatibility -#define _normal _normalWS -#define _modelNormal _normalMS -#define _position _positionMS -#define _eyePosition _positionES +LAYOUT(binding=0) uniform sampler2D simpleTexture; -<@include procedural/ProceduralCommon.slh@> - -#line 1001 -//PROCEDURAL_BLOCK_BEGIN - -vec3 getProceduralColor() { - return _color.rgb; -} - -float getProceduralColors(inout vec3 diffuse, inout vec3 specular, inout float shininess) { - return 1.0; -} - -float getProceduralFragment(inout ProceduralFragment proceduralData) { - return 1.0; -} - -float getProceduralFragmentWithPosition(inout ProceduralFragmentWithPosition proceduralData) { - return 1.0; -} - -//PROCEDURAL_BLOCK_END - -#line 2030 void main(void) { - vec3 normal = normalize(_normalWS.xyz); - vec3 diffuse = _color.rgb; - float roughness = DEFAULT_ROUGHNESS; - float metallic = DEFAULT_METALLIC; - vec3 emissive = DEFAULT_EMISSIVE; - float occlusion = DEFAULT_OCCLUSION; - float scattering = DEFAULT_SCATTERING; + vec4 texel = texture(simpleTexture, _texCoord0); + texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); + texel.rgb *= _color.rgb; + texel.a *= abs(_color.a); - float emissiveAmount = 0.0; +<@if HIFI_USE_FADE@> + vec3 fadeEmissive; + FadeObjectParams fadeParams; + <$fetchFadeObjectParamsInstanced(fadeParams)$> + applyFade(fadeParams, _positionWS.xyz, fadeEmissive); +<@endif@> -#if defined(PROCEDURAL_V1) - diffuse = getProceduralColor().rgb; - emissiveAmount = 1.0; - emissive = vec3(1.0); -#elif defined(PROCEDURAL_V2) - vec3 specular = DEFAULT_SPECULAR; - float shininess = DEFAULT_SHININESS; - emissiveAmount = getProceduralColors(diffuse, specular, shininess); - roughness = max(0.0, 1.0 - shininess / 128.0); - metallic = length(specular); - emissive = vec3(clamp(emissiveAmount, 0.0, 1.0)); -#elif defined(PROCEDURAL_V3) || defined(PROCEDURAL_V4) -#if defined(PROCEDURAL_V3) - ProceduralFragment proceduralData = ProceduralFragment( -#else - TransformCamera cam = getTransformCamera(); - vec4 position = cam._viewInverse * _positionES; - ProceduralFragmentWithPosition proceduralData = ProceduralFragmentWithPosition( - position.xyz, -#endif - normal, - diffuse, - DEFAULT_SPECULAR, - emissive, - 1.0, - roughness, - metallic, - occlusion, - scattering - ); +<@if not HIFI_USE_UNLIT@> + <@if HIFI_USE_FORWARD or HIFI_USE_TRANSLUCENT@> + float metallic = DEFAULT_METALLIC; + vec3 fresnel = getFresnelF0(metallic, texel.rgb); -#if defined(PROCEDURAL_V3) - emissiveAmount = getProceduralFragment(proceduralData); -#else - emissiveAmount = getProceduralFragmentWithPosition(proceduralData); -#endif - normal = proceduralData.normal; - diffuse = proceduralData.diffuse; - roughness = proceduralData.roughness; - metallic = proceduralData.metallic; - emissive = proceduralData.emissive; - occlusion = proceduralData.occlusion; - scattering = proceduralData.scattering; + TransformCamera cam = getTransformCamera(); + vec3 fragPosition = _positionES.xyz; + <@endif@> +<@endif@> -#if defined(PROCEDURAL_V4) - position = vec4(proceduralData.position, 1.0); - vec4 posClip = cam._projection * (cam._view * position); - gl_FragDepth = 0.5 * (posClip.z / posClip.w + 1.0); -#endif - -#endif - - if (emissiveAmount > 0.0) { - packDeferredFragmentLightmap( - normal, +<@if not HIFI_USE_UNLIT@> + <@if HIFI_USE_TRANSLUCENT@> + _fragColor0 = vec4(evalGlobalLightingAlphaBlended( + cam._viewInverse, 1.0, - diffuse, - roughness, + DEFAULT_OCCLUSION, + fragPosition, + normalize(_normalWS) * (2.0 * float(gl_FrontFacing) - 1.0), + texel.rgb, + fresnel, metallic, - emissive); - } else { + DEFAULT_EMISSIVE + <@if HIFI_USE_FADE@> + + fadeEmissive + <@endif@> + , + DEFAULT_ROUGHNESS, texel.a), + texel.a); + <@elif HIFI_USE_FORWARD@> + _fragColor0 = vec4(evalSkyboxGlobalColor( + cam._viewInverse, + 1.0, + DEFAULT_OCCLUSION, + fragPosition, + normalize(_normalWS) * (2.0 * float(gl_FrontFacing) - 1.0), + texel.rgb, + fresnel, + metallic, + DEFAULT_ROUGHNESS), + texel.a); + <@else@> packDeferredFragment( - normal, + normalize(_normalWS) * (2.0 * float(gl_FrontFacing) - 1.0), 1.0, - diffuse, - roughness, - metallic, - emissive, - occlusion, - scattering); - } + texel.rgb, + DEFAULT_ROUGHNESS, + DEFAULT_METALLIC, + DEFAULT_EMISSIVE + <@if HIFI_USE_FADE@> + + fadeEmissive + <@endif@> + , + DEFAULT_OCCLUSION, + DEFAULT_SCATTERING); + <@endif@> +<@else@> + <@if HIFI_USE_FORWARD or HIFI_USE_TRANSLUCENT@> + _fragColor0 = isUnlitEnabled() * vec4(texel.rgb + <@if HIFI_USE_FADE@> + + fadeEmissive + <@endif@> + , texel.a); + <@else@> + packDeferredFragmentUnlit( + normalize(_normalWS) * (2.0 * float(gl_FrontFacing) - 1.0), + 1.0, + texel.rgb + <@if HIFI_USE_FADE@> + + fadeEmissive + <@endif@> + ); + <@endif@> +<@endif@> } diff --git a/libraries/render-utils/src/simple.slv b/libraries/render-utils/src/simple.slv index 460ed53281..e47af5d23f 100644 --- a/libraries/render-utils/src/simple.slv +++ b/libraries/render-utils/src/simple.slv @@ -1,10 +1,8 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> +// <$_SCRIBE_FILENAME$> // Generated on <$_SCRIBE_DATE$> // -// simple.vert -// vertex shader -// // Created by Andrzej Kapolka on 9/15/14. // Copyright 2014 High Fidelity, Inc. // @@ -19,22 +17,41 @@ <@include render-utils/ShaderConstants.h@> +<@if HIFI_USE_FADE@> + <@include Fade.slh@> + <$declareFadeVertexInstanced()$> + + layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS; +<@endif@> + +<@if not HIFI_USE_UNLIT@> + <@if HIFI_USE_FORWARD or HIFI_USE_TRANSLUCENT@> + layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; + <@endif@> +<@endif@> layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_NORMAL_MS) out vec3 _normalMS; layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; -layout(location=RENDER_UTILS_ATTR_POSITION_MS) out vec4 _positionMS; -layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; void main(void) { _color = color_sRGBAToLinear(inColor); - _texCoord01.xy = inTexCoord0.st; - _positionMS = inPosition; - _normalMS = inNormal.xyz; + _texCoord01 = vec4(inTexCoord0.st, 0.0, 0.0); - // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToEyeAndClipPos(cam, obj, inPosition, _positionES, gl_Position)$> +<@if not HIFI_USE_UNLIT@> + <@if HIFI_USE_FORWARD or HIFI_USE_TRANSLUCENT@> + <$transformModelToEyeAndClipPos(cam, obj, inPosition, _positionES, gl_Position)$> + <@else@> + <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> + <@endif@> +<@else@> + <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> +<@endif@> + +<@if HIFI_USE_FADE@> + <$transformModelToWorldPos(obj, inPosition, _positionWS)$> + <$passThroughFadeObjectParams()$> +<@endif@> <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normalWS)$> } \ No newline at end of file diff --git a/libraries/render-utils/src/simple_fade.slv b/libraries/render-utils/src/simple_fade.slv deleted file mode 100644 index 0bbd8eac39..0000000000 --- a/libraries/render-utils/src/simple_fade.slv +++ /dev/null @@ -1,47 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// simple_fade.vert -// vertex shader -// -// Created by Olivier Prat on 06/04/17. -// 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 gpu/Inputs.slh@> -<@include gpu/Color.slh@> -<@include gpu/Transform.slh@> -<$declareStandardTransform()$> - -<@include Fade.slh@> -<$declareFadeVertexInstanced()$> - -<@include render-utils/ShaderConstants.h@> - -// the interpolated normal -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_NORMAL_MS) out vec3 _normalMS; -layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; -layout(location=RENDER_UTILS_ATTR_POSITION_MS) out vec4 _positionMS; -layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS; - -void main(void) { - _color = color_sRGBAToLinear(inColor); - _texCoord01.xy = inTexCoord0.st; - _positionMS = inPosition; - _normalMS = inNormal.xyz; - - // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToEyeAndClipPos(cam, obj, inPosition, _positionES, gl_Position)$> - <$transformModelToWorldPos(obj, inPosition, _positionWS)$> - <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normalWS)$> - <$passThroughFadeObjectParams()$> -} \ No newline at end of file diff --git a/libraries/render-utils/src/simple_opaque_web_browser.slf b/libraries/render-utils/src/simple_opaque_web_browser.slf deleted file mode 100644 index df789ee22b..0000000000 --- a/libraries/render-utils/src/simple_opaque_web_browser.slf +++ /dev/null @@ -1,34 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// simple_opaque_web_browser.frag -// fragment shader -// -// Created by Anthony Thibault on 7/25/16. -// Copyright 2016 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 gpu/Color.slh@> -<@include DeferredBufferWrite.slh@> - -<@include render-utils/ShaderConstants.h@> - -// the albedo texture -LAYOUT(binding=0) uniform sampler2D originalTexture; - -// the interpolated normal -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw - -void main(void) { - vec4 texel = texture(originalTexture, _texCoord0); - texel = color_sRGBAToLinear(texel); - packDeferredFragmentUnlit(normalize(_normalWS), 1.0, _color.rgb * texel.rgb); -} diff --git a/libraries/render-utils/src/simple_transparent.slf b/libraries/render-utils/src/simple_procedural.slf similarity index 76% rename from libraries/render-utils/src/simple_transparent.slf rename to libraries/render-utils/src/simple_procedural.slf index 6d8348f50c..5b0eb62cca 100644 --- a/libraries/render-utils/src/simple_transparent.slf +++ b/libraries/render-utils/src/simple_procedural.slf @@ -1,37 +1,39 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> +// <$_SCRIBE_FILENAME$> // Generated on <$_SCRIBE_DATE$> // -// simple_transparent.frag -// fragment shader -// // Created by Andrzej Kapolka on 9/15/14. // Copyright 2014 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 DefaultMaterials.slh@> -<@include DeferredGlobalLight.slh@> -<$declareEvalGlobalLightingAlphaBlendedWithHaze()$> +<@if not HIFI_USE_TRANSLUCENT@> + <@include DeferredBufferWrite.slh@> +<@else@> + <@include DefaultMaterials.slh@> + + <@include GlobalLight.slh@> + <$declareEvalGlobalLightingAlphaBlended()$> + + layout(location=0) out vec4 _fragColor0; +<@endif@> <@include gpu/Transform.slh@> <$declareStandardCameraTransform()$> <@include render-utils/ShaderConstants.h@> -// the interpolated normal -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; +layout(location=RENDER_UTILS_ATTR_POSITION_MS) in vec4 _positionMS; +layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; layout(location=RENDER_UTILS_ATTR_NORMAL_MS) in vec3 _normalMS; +layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; #define _texCoord0 _texCoord01.xy #define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_POSITION_MS) in vec4 _positionMS; -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; - -layout(location=0) out vec4 _fragColor0; // For retro-compatibility #define _normal _normalWS @@ -42,7 +44,6 @@ layout(location=0) out vec4 _fragColor0; <@include procedural/ProceduralCommon.slh@> #line 1001 - //PROCEDURAL_BLOCK_BEGIN vec3 getProceduralColor() { @@ -65,21 +66,26 @@ float getProceduralFragmentWithPosition(inout ProceduralFragmentWithPosition pro #line 2030 void main(void) { - vec3 normal = normalize(_normalWS.xyz); + vec3 normal = normalize(_normalWS.xyz) * (2.0 * float(gl_FrontFacing) - 1.0); vec3 diffuse = _color.rgb; - float alpha = _color.a; - float occlusion = DEFAULT_OCCLUSION; vec3 fresnel = DEFAULT_FRESNEL; + float roughness = DEFAULT_ROUGHNESS; float metallic = DEFAULT_METALLIC; vec3 emissive = DEFAULT_EMISSIVE; - float roughness = DEFAULT_ROUGHNESS; + float occlusion = DEFAULT_OCCLUSION; + float scattering = DEFAULT_SCATTERING; float emissiveAmount = 0.0; +<@if HIFI_USE_TRANSLUCENT@> + float alpha = _color.a; TransformCamera cam = getTransformCamera(); vec3 posEye = _positionES.xyz; +<@else@> + float alpha = 1.0; +<@endif@> -#ifdef PROCEDURAL_V1 +#if defined(PROCEDURAL_V1) diffuse = getProceduralColor().rgb; emissiveAmount = 1.0; emissive = vec3(1.0); @@ -94,6 +100,7 @@ void main(void) { #if defined(PROCEDURAL_V3) ProceduralFragment proceduralData = ProceduralFragment( #else + TransformCamera cam = getTransformCamera(); vec4 position = cam._viewInverse * _positionES; ProceduralFragmentWithPosition proceduralData = ProceduralFragmentWithPosition( position.xyz, @@ -106,7 +113,7 @@ void main(void) { roughness, metallic, occlusion, - DEFAULT_SCATTERING + scattering ); #if defined(PROCEDURAL_V3) @@ -114,29 +121,53 @@ void main(void) { #else emissiveAmount = getProceduralFragmentWithPosition(proceduralData); #endif - occlusion = proceduralData.occlusion; normal = proceduralData.normal; diffuse = proceduralData.diffuse; fresnel = proceduralData.specular; + roughness = proceduralData.roughness; metallic = proceduralData.metallic; emissive = proceduralData.emissive; - roughness = proceduralData.roughness; + occlusion = proceduralData.occlusion; + scattering = proceduralData.scattering; alpha = proceduralData.alpha; #if defined(PROCEDURAL_V4) position = vec4(proceduralData.position, 1.0); vec4 posEye4 = cam._view * position; +<@if HIFI_USE_TRANSLUCENT@> posEye = posEye4.xyz; +<@endif@> vec4 posClip = cam._projection * posEye4; gl_FragDepth = 0.5 * (posClip.z / posClip.w + 1.0); #endif #endif +<@if not HIFI_USE_TRANSLUCENT@> + if (emissiveAmount > 0.0) { + packDeferredFragmentLightmap( + normal, + 1.0, + diffuse, + roughness, + metallic, + emissive); + } else { + packDeferredFragment( + normal, + 1.0, + diffuse, + roughness, + metallic, + emissive, + occlusion, + scattering); + } +<@else@> if (emissiveAmount > 0.0) { _fragColor0 = vec4(diffuse, alpha); } else { - _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze( + _fragColor0 = vec4(evalGlobalLightingAlphaBlended( cam._viewInverse, 1.0, occlusion, @@ -149,4 +180,5 @@ void main(void) { roughness, alpha), alpha); } +<@endif@> } diff --git a/libraries/render-utils/src/simple_procedural.slv b/libraries/render-utils/src/simple_procedural.slv new file mode 100644 index 0000000000..a8d494f72d --- /dev/null +++ b/libraries/render-utils/src/simple_procedural.slv @@ -0,0 +1,57 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// <$_SCRIBE_FILENAME$> +// Generated on <$_SCRIBE_DATE$> +// +// Created by Andrzej Kapolka on 9/15/14. +// Copyright 2014 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 gpu/Inputs.slh@> +<@include gpu/Color.slh@> +<@include gpu/Transform.slh@> +<$declareStandardTransform()$> + +<@include render-utils/ShaderConstants.h@> + +<@if HIFI_USE_DEFORMED or HIFI_USE_DEFORMEDDQ@> + <@include MeshDeformer.slh@> + <@if HIFI_USE_DEFORMED@> + <$declareMeshDeformer(1, _SCRIBE_NULL, 1, _SCRIBE_NULL, 1)$> + <@else@> + <$declareMeshDeformer(1, _SCRIBE_NULL, 1, 1, 1)$> + <@endif@> + <$declareMeshDeformerActivation(1, 1)$> +<@endif@> + +layout(location=RENDER_UTILS_ATTR_POSITION_MS) out vec4 _positionMS; +layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; +layout(location=RENDER_UTILS_ATTR_NORMAL_MS) out vec3 _normalMS; +layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; +layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; +layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; + +void main(void) { + vec4 positionMS = inPosition; + vec3 normalMS = inNormal.xyz; + +<@if HIFI_USE_DEFORMED or HIFI_USE_DEFORMEDDQ@> + evalMeshDeformer(inPosition, positionMS, inNormal.xyz, normalMS, + meshDeformer_doSkinning(_drawCallInfo.y), inSkinClusterIndex, inSkinClusterWeight, + meshDeformer_doBlendshape(_drawCallInfo.y), gl_VertexID); +<@endif@> + + _positionMS = positionMS; + _normalMS = normalMS; + + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToEyeAndClipPos(cam, obj, positionMS, _positionES, gl_Position)$> + <$transformModelToWorldDir(cam, obj, normalMS, _normalWS)$> + + _color = color_sRGBAToLinear(inColor); + _texCoord01 = vec4(inTexCoord0.st, 0.0, 0.0); +} \ No newline at end of file diff --git a/libraries/render-utils/src/simple_textured.slf b/libraries/render-utils/src/simple_textured.slf deleted file mode 100644 index dbc49fcb5d..0000000000 --- a/libraries/render-utils/src/simple_textured.slf +++ /dev/null @@ -1,44 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// simple_textured.frag -// fragment shader -// -// Created by Clement Brisset on 5/29/15. -// Copyright 2014 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 gpu/Color.slh@> -<@include DeferredBufferWrite.slh@> - -<@include render-utils/ShaderConstants.h@> - -// the albedo texture -LAYOUT(binding=0) uniform sampler2D originalTexture; - -// the interpolated normal -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw - -void main(void) { - vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); - texel.rgb *= _color.rgb; - - packDeferredFragment( - normalize(_normalWS), - 1.0, - texel.rgb, - DEFAULT_ROUGHNESS, - DEFAULT_METALLIC, - DEFAULT_EMISSIVE, - DEFAULT_OCCLUSION, - DEFAULT_SCATTERING); -} \ No newline at end of file diff --git a/libraries/render-utils/src/simple_textured_fade.slf b/libraries/render-utils/src/simple_textured_fade.slf deleted file mode 100644 index 5a9eb0688e..0000000000 --- a/libraries/render-utils/src/simple_textured_fade.slf +++ /dev/null @@ -1,66 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// simple_textured_fade.frag -// fragment shader -// -// Created by Olivier Prat on 06/05/17. -// 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 gpu/Color.slh@> -<@include DeferredBufferWrite.slh@> - -<@include Fade.slh@> - -<@include render-utils/ShaderConstants.h@> - -// the albedo texture -LAYOUT(binding=0) uniform sampler2D originalTexture; - -// the interpolated normal -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; - -// Declare after all samplers to prevent sampler location mix up with originalTexture -<$declareFadeFragmentInstanced()$> - -void main(void) { - vec3 fadeEmissive; - FadeObjectParams fadeParams; - - <$fetchFadeObjectParamsInstanced(fadeParams)$> - applyFade(fadeParams, _positionWS.xyz, fadeEmissive); - - vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); - texel.rgb *= _color.rgb; - texel.a *= abs(_color.a); - - const float ALPHA_THRESHOLD = 0.999; - if (texel.a < ALPHA_THRESHOLD) { - packDeferredFragmentTranslucent( - normalize(_normalWS), - texel.a, - texel.rgb + fadeEmissive, - DEFAULT_ROUGHNESS); - } else { - packDeferredFragment( - normalize(_normalWS), - 1.0, - texel.rgb, - DEFAULT_ROUGHNESS, - DEFAULT_METALLIC, - DEFAULT_EMISSIVE + fadeEmissive, - DEFAULT_OCCLUSION, - DEFAULT_SCATTERING); - } -} \ No newline at end of file diff --git a/libraries/render-utils/src/simple_textured_unlit.slf b/libraries/render-utils/src/simple_textured_unlit.slf deleted file mode 100644 index 475428f0ae..0000000000 --- a/libraries/render-utils/src/simple_textured_unlit.slf +++ /dev/null @@ -1,49 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// simple_textured_unlit.frag -// fragment shader -// -// Created by Clement Brisset on 5/29/15. -// Copyright 2014 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 gpu/Color.slh@> -<@include DeferredBufferWrite.slh@> - -<@include render-utils/ShaderConstants.h@> - -// the albedo texture -LAYOUT(binding=0) uniform sampler2D originalTexture; - -// the interpolated normal -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw - -void main(void) { - vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); - texel.rgb *= _color.rgb; - texel.a *= abs(_color.a); - - const float ALPHA_THRESHOLD = 0.999; - if (texel.a < ALPHA_THRESHOLD) { - packDeferredFragmentTranslucent( - normalize(_normalWS), - texel.a, - texel.rgb, - DEFAULT_ROUGHNESS); - } else { - packDeferredFragmentUnlit( - normalize(_normalWS), - 1.0, - texel.rgb); - } -} \ No newline at end of file diff --git a/libraries/render-utils/src/simple_textured_unlit_fade.slf b/libraries/render-utils/src/simple_textured_unlit_fade.slf deleted file mode 100644 index d0ba4c13fe..0000000000 --- a/libraries/render-utils/src/simple_textured_unlit_fade.slf +++ /dev/null @@ -1,61 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// simple_textured_unlit_fade.frag -// fragment shader -// -// Created by Olivier Prat on 06/05/17. -// 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 gpu/Color.slh@> -<@include DeferredBufferWrite.slh@> - -<@include Fade.slh@> - -<@include render-utils/ShaderConstants.h@> - -// the albedo texture -LAYOUT(binding=0) uniform sampler2D originalTexture; - -// the interpolated normal -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; - -// Declare after all samplers to prevent sampler location mix up with originalTexture -<$declareFadeFragmentInstanced()$> - -void main(void) { - vec3 fadeEmissive; - FadeObjectParams fadeParams; - - <$fetchFadeObjectParamsInstanced(fadeParams)$> - applyFade(fadeParams, _positionWS.xyz, fadeEmissive); - - vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); - texel.rgb *= _color.rgb; - texel.a *= abs(_color.a); - - const float ALPHA_THRESHOLD = 0.999; - if (texel.a < ALPHA_THRESHOLD) { - packDeferredFragmentTranslucent( - normalize(_normalWS), - texel.a, - texel.rgb + fadeEmissive, - DEFAULT_ROUGHNESS); - } else { - packDeferredFragmentUnlit( - normalize(_normalWS), - 1.0, - texel.rgb + fadeEmissive); - } -} \ No newline at end of file diff --git a/libraries/render-utils/src/simple_transparent_textured.slf b/libraries/render-utils/src/simple_transparent_textured.slf deleted file mode 100644 index 9f8a88c7c2..0000000000 --- a/libraries/render-utils/src/simple_transparent_textured.slf +++ /dev/null @@ -1,60 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// simple_transparent_textured.frag -// fragment shader -// -// Created by Sam Gateau on 4/3/17. -// 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 DefaultMaterials.slh@> - -<@include gpu/Color.slh@> -<@include render-utils/ShaderConstants.h@> - -<@include DeferredGlobalLight.slh@> -<$declareEvalGlobalLightingAlphaBlendedWithHaze()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -LAYOUT(binding=0) uniform sampler2D originalTexture; - -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw - -layout(location=0) out vec4 _fragColor0; - -void main(void) { - vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); - vec3 albedo = _color.xyz * texel.xyz; - float alpha = _color.a * texel.a; - float metallic = DEFAULT_METALLIC; - - vec3 fresnel = getFresnelF0(metallic, albedo); - - TransformCamera cam = getTransformCamera(); - vec3 fragPosition = _positionES.xyz; - - _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze( - cam._viewInverse, - 1.0, - DEFAULT_OCCLUSION, - fragPosition, - normalize(_normalWS), - albedo, - fresnel, - metallic, - DEFAULT_EMISSIVE, - DEFAULT_ROUGHNESS, alpha), - alpha); -} \ No newline at end of file diff --git a/libraries/render-utils/src/simple_transparent_textured_fade.slf b/libraries/render-utils/src/simple_transparent_textured_fade.slf deleted file mode 100644 index d401989f90..0000000000 --- a/libraries/render-utils/src/simple_transparent_textured_fade.slf +++ /dev/null @@ -1,72 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// simple_transparent_textured_fade.frag -// fragment shader -// -// Created by Olivier Prat on 06/05/17. -// 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 gpu/Color.slh@> - -<@include DeferredBufferWrite.slh@> -<@include DeferredGlobalLight.slh@> -<$declareEvalGlobalLightingAlphaBlendedWithHaze()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -<@include Fade.slh@> - -<@include render-utils/ShaderConstants.h@> - -// the albedo texture -LAYOUT(binding=0) uniform sampler2D originalTexture; - -layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; - -// Declare after all samplers to prevent sampler location mix up with originalTexture -<$declareFadeFragmentInstanced()$> - -void main(void) { - vec3 fadeEmissive; - FadeObjectParams fadeParams; - - <$fetchFadeObjectParamsInstanced(fadeParams)$> - applyFade(fadeParams, _positionWS.xyz, fadeEmissive); - - vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); - texel.rgb *= _color.rgb; - texel.a *= abs(_color.a); - - vec3 fragPosition = _positionES.xyz; - vec3 fragNormal = normalize(_normalWS); - - TransformCamera cam = getTransformCamera(); - - _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze( - cam._viewInverse, - 1.0, - 1.0, - fragPosition, - fragNormal, - texel.rgb, - DEFAULT_FRESNEL, - 0.0f, - fadeEmissive, - DEFAULT_ROUGHNESS, - texel.a), - texel.a); -} \ No newline at end of file diff --git a/libraries/render-utils/src/simple_transparent_textured_unlit.slf b/libraries/render-utils/src/simple_transparent_textured_unlit.slf deleted file mode 100644 index 42a8270274..0000000000 --- a/libraries/render-utils/src/simple_transparent_textured_unlit.slf +++ /dev/null @@ -1,36 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// simple_transparent_textured_unlit.frag -// fragment shader -// -// Created by Sam Gateau on 4/3/17. -// 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 gpu/Color.slh@> - -<@include render-utils/ShaderConstants.h@> - -// the albedo texture -LAYOUT(binding=0) uniform sampler2D originalTexture; - -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw - -layout(location=0) out vec4 _fragColor0; - -void main(void) { - vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); - texel.rgb *= _color.rgb; - texel.a *= abs(_color.a); - - _fragColor0 = texel; -} \ No newline at end of file diff --git a/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf b/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf deleted file mode 100644 index afc0c94575..0000000000 --- a/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf +++ /dev/null @@ -1,48 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// simple_transparent_textured_unlit_fade.frag -// fragment shader -// -// Created by Olivier Prat on 06/05/17. -// 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 gpu/Color.slh@> - -<@include Fade.slh@> - -<@include render-utils/ShaderConstants.h@> - -// the albedo texture -LAYOUT(binding=0) uniform sampler2D originalTexture; - -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw -layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; - -layout(location=0) out vec4 _fragColor0; - -// Declare after all samplers to prevent sampler location mix up with originalTexture -<$declareFadeFragmentInstanced()$> - -void main(void) { - vec3 fadeEmissive; - FadeObjectParams fadeParams; - - <$fetchFadeObjectParamsInstanced(fadeParams)$> - applyFade(fadeParams, _positionWS.xyz, fadeEmissive); - - vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); - texel.rgb *= _color.rgb; - texel.a *= abs(_color.a); - - _fragColor0 = vec4(texel.rgb + fadeEmissive, texel.a); -} \ No newline at end of file diff --git a/libraries/render-utils/src/simple_transparent_web_browser.slf b/libraries/render-utils/src/simple_transparent_web_browser.slf deleted file mode 100644 index 599fd3d87f..0000000000 --- a/libraries/render-utils/src/simple_transparent_web_browser.slf +++ /dev/null @@ -1,38 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// simple_transparent_web_browser.frag -// fragment shader -// -// Created by Anthony Thibault on 7/25/16. -// Copyright 2016 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 gpu/Color.slh@> -<@include DeferredBufferWrite.slh@> - -<@include render-utils/ShaderConstants.h@> - -// the albedo texture -LAYOUT(binding=0) uniform sampler2D originalTexture; - -// the interpolated normal -layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; -layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; -#define _texCoord0 _texCoord01.xy -#define _texCoord1 _texCoord01.zw - -void main(void) { - vec4 texel = texture(originalTexture, _texCoord0); - texel = color_sRGBAToLinear(texel); - packDeferredFragmentTranslucent( - normalize(_normalWS), - _color.a * texel.a, - _color.rgb * texel.rgb, - DEFAULT_ROUGHNESS); -} diff --git a/libraries/render-utils/src/text/Font.cpp b/libraries/render-utils/src/text/Font.cpp index c69db5e055..eee6a7daea 100644 --- a/libraries/render-utils/src/text/Font.cpp +++ b/libraries/render-utils/src/text/Font.cpp @@ -15,9 +15,7 @@ static std::mutex fontMutex; -gpu::PipelinePointer Font::_deferredPipeline; -gpu::PipelinePointer Font::_forwardPipeline; -gpu::PipelinePointer Font::_transparentPipeline; +std::map, gpu::PipelinePointer> Font::_pipelines; gpu::Stream::FormatPointer Font::_format; struct TextureVertex { @@ -221,31 +219,28 @@ void Font::read(QIODevice& in) { } void Font::setupGPU() { - if (!_deferredPipeline) { - // Setup render pipeline - { - { - auto state = std::make_shared(); - state->setCullMode(gpu::State::CULL_BACK); - state->setDepthTest(true, true, gpu::LESS_EQUAL); - state->setBlendFunction(false, - gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, - gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); - PrepareStencil::testMaskDrawShape(*state); - _deferredPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(shader::render_utils::program::sdf_text3D), state); - _forwardPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(shader::render_utils::program::forward_sdf_text3D), state); - } + if (_pipelines.empty()) { + using namespace shader::render_utils::program; - { - auto state = std::make_shared(); - state->setCullMode(gpu::State::CULL_BACK); - state->setDepthTest(true, true, gpu::LESS_EQUAL); - state->setBlendFunction(true, - gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, - gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + static const std::vector> keys = { + std::make_tuple(false, false, false, sdf_text3D), std::make_tuple(true, false, false, sdf_text3D_translucent), + std::make_tuple(false, true, false, sdf_text3D_unlit), std::make_tuple(true, true, false, sdf_text3D_translucent_unlit), + std::make_tuple(false, false, true, sdf_text3D_forward), std::make_tuple(true, false, true, sdf_text3D_forward/*sdf_text3D_translucent_forward*/), + std::make_tuple(false, true, true, sdf_text3D_translucent_unlit/*sdf_text3D_unlit_forward*/), std::make_tuple(true, true, true, sdf_text3D_translucent_unlit/*sdf_text3D_translucent_unlit_forward*/) + }; + for (auto& key : keys) { + auto state = std::make_shared(); + state->setCullMode(gpu::State::CULL_BACK); + state->setDepthTest(true, true, gpu::LESS_EQUAL); + state->setBlendFunction(std::get<0>(key), + gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, + gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + if (std::get<0>(key)) { PrepareStencil::testMask(*state); - _transparentPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(shader::render_utils::program::sdf_text3D_transparent), state); + } else { + PrepareStencil::testMaskDrawShape(*state); } + _pipelines[std::make_tuple(std::get<0>(key), std::get<1>(key), std::get<2>(key))] = gpu::Pipeline::create(gpu::Shader::createProgram(std::get<3>(key)), state); } // Sanity checks @@ -349,7 +344,7 @@ void Font::buildVertices(Font::DrawInfo& drawInfo, const QString& str, const glm } void Font::drawString(gpu::Batch& batch, Font::DrawInfo& drawInfo, const QString& str, const glm::vec4& color, - EffectType effectType, const glm::vec2& origin, const glm::vec2& bounds, bool forward) { + EffectType effectType, const glm::vec2& origin, const glm::vec2& bounds, bool unlit, bool forward) { if (str == "") { return; } @@ -376,7 +371,7 @@ void Font::drawString(gpu::Batch& batch, Font::DrawInfo& drawInfo, const QString } // need the gamma corrected color here - batch.setPipeline(color.a < 1.0f ? _transparentPipeline : (forward ? _forwardPipeline : _deferredPipeline)); + batch.setPipeline(_pipelines[std::make_tuple(color.a < 1.0f, unlit, forward)]); batch.setInputFormat(_format); batch.setInputBuffer(0, drawInfo.verticesBuffer, 0, _format->getChannels().at(0)._stride); batch.setResourceTexture(render_utils::slot::texture::TextFont, _texture); diff --git a/libraries/render-utils/src/text/Font.h b/libraries/render-utils/src/text/Font.h index 893ab59981..be1e890e3d 100644 --- a/libraries/render-utils/src/text/Font.h +++ b/libraries/render-utils/src/text/Font.h @@ -46,11 +46,10 @@ public: // Render string to batch void drawString(gpu::Batch& batch, DrawInfo& drawInfo, const QString& str, const glm::vec4& color, EffectType effectType, - const glm::vec2& origin, const glm::vec2& bound, bool forward); + const glm::vec2& origin, const glm::vec2& bound, bool unlit, bool forward); static Pointer load(const QString& family); - private: static Pointer load(QIODevice& fontFile); QStringList tokenizeForWrapping(const QString& str) const; @@ -80,9 +79,7 @@ private: gpu::TexturePointer _texture; gpu::BufferStreamPointer _stream; - static gpu::PipelinePointer _deferredPipeline; - static gpu::PipelinePointer _forwardPipeline; - static gpu::PipelinePointer _transparentPipeline; + static std::map, gpu::PipelinePointer> _pipelines; static gpu::Stream::FormatPointer _format; }; diff --git a/libraries/render-utils/src/toneMapping.slf b/libraries/render-utils/src/toneMapping.slf index 3fe53d9be1..4f7ed6374d 100644 --- a/libraries/render-utils/src/toneMapping.slf +++ b/libraries/render-utils/src/toneMapping.slf @@ -20,6 +20,7 @@ struct ToneMappingParams { ivec4 _toneCurve_s0_s1_s2; }; +const float GAMMA_22 = 2.2; const float INV_GAMMA_22 = 1.0 / 2.2; const int ToneCurveNone = 0; const int ToneCurveGamma22 = 1; @@ -51,13 +52,20 @@ void main(void) { vec3 tonedColor = srcColor; if (toneCurve == ToneCurveFilmic) { vec3 x = max(vec3(0.0), srcColor-0.004); - tonedColor = (x * (6.2 * x + 0.5)) / (x * (6.2 * x + 1.7) + 0.06); + tonedColor = pow((x * (6.2 * x + 0.5)) / (x * (6.2 * x + 1.7) + 0.06), vec3(GAMMA_22)); } else if (toneCurve == ToneCurveReinhard) { tonedColor = srcColor/(1.0 + srcColor); - tonedColor = pow(tonedColor, vec3(INV_GAMMA_22)); } else if (toneCurve == ToneCurveGamma22) { - tonedColor = pow(srcColor, vec3(INV_GAMMA_22)); - } // else None toned = src + // We use glEnable(GL_FRAMEBUFFER_SRGB), which automatically converts textures from RGB to SRGB + // when writing from an RGB framebuffer to an SRGB framebuffer (note that it doesn't do anything + // when writing from an SRGB framebuffer to an RGB framebuffer). + // Since the conversion happens automatically, we don't need to do anything in this shader + } else { + // toneCurve == ToneCurveNone + // For debugging purposes, we may want to see what the colors look like before the automatic OpenGL + // conversion mentioned above, so we undo it here + tonedColor = pow(srcColor, vec3(GAMMA_22)); + } outFragColor = vec4(tonedColor, 1.0); } diff --git a/libraries/render-utils/src/web_browser.slf b/libraries/render-utils/src/web_browser.slf new file mode 100644 index 0000000000..f746916d3d --- /dev/null +++ b/libraries/render-utils/src/web_browser.slf @@ -0,0 +1,74 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// <$_SCRIBE_FILENAME$> +// Generated on <$_SCRIBE_DATE$> +// +// Created by Anthony Thibault on 7/25/16. +// Copyright 2016 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 gpu/Color.slh@> +<@include render-utils/ShaderConstants.h@> + +<@if HIFI_USE_FORWARD@> + <@include LightingModel.slh@> + <@include graphics/Haze.slh@> + + <@include gpu/Transform.slh@> + <$declareStandardCameraTransform()$> + + <@include graphics/Light.slh@> + <$declareLightBuffer()$> + + layout(location=0) out vec4 _fragColor0; +<@else@> + <@include DeferredBufferWrite.slh@> +<@endif@> + +LAYOUT(binding=0) uniform sampler2D webTexture; + +<@if HIFI_USE_FORWARD@> + layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS; + layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; +<@else@> + layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; +<@endif@> +layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; +layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; +#define _texCoord0 _texCoord01.xy +#define _texCoord1 _texCoord01.zw + +void main(void) { + vec4 texel = texture(webTexture, _texCoord0); + texel = color_sRGBAToLinear(texel); + texel *= _color; + +<@if HIFI_USE_FORWARD@> + _fragColor0 = texel; + + if (isHazeEnabled() > 0.0) { + // no light attenuation because we're unlit + + TransformCamera cam = getTransformCamera(); + + Light light = getKeyLight(); + vec3 lightDirectionWS = getLightDirection(light); + + if ((hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) { + vec4 hazeColor = computeHazeColor( + _positionES.xyz, + _positionWS.xyz, + cam._viewInverse[3].xyz, + lightDirectionWS + ); + + _fragColor0.xyz = mix(_fragColor0.rgb, hazeColor.rgb, hazeColor.a); + } + } +<@else@> + packDeferredFragmentUnlit(normalize(_normalWS), 1.0, texel.rgb); +<@endif@> +} diff --git a/libraries/render-utils/src/web_browser.slv b/libraries/render-utils/src/web_browser.slv new file mode 100644 index 0000000000..07b4d7d3d7 --- /dev/null +++ b/libraries/render-utils/src/web_browser.slv @@ -0,0 +1,41 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// <$_SCRIBE_FILENAME$> +// Generated on <$_SCRIBE_DATE$> +// +// Created by Andrzej Kapolka on 9/15/14. +// Copyright 2014 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 gpu/Inputs.slh@> +<@include gpu/Color.slh@> +<@include gpu/Transform.slh@> +<$declareStandardTransform()$> + +<@include render-utils/ShaderConstants.h@> + +<@if HIFI_USE_FORWARD@> + layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS; + layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; +<@else@> + layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; +<@endif@> +layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; +layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; + +void main(void) { + _color = color_sRGBAToLinear(inColor); + _texCoord01 = vec4(inTexCoord0.st, 0.0, 0.0); + + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); +<@if HIFI_USE_FORWARD@> + <$transformModelToWorldAndEyeAndClipPos(cam, obj, inPosition, _positionWS, _positionES, gl_Position)$> +<@else@> + <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> + <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normalWS)$> +<@endif@> +} \ No newline at end of file diff --git a/libraries/render/src/render/Args.h b/libraries/render/src/render/Args.h index 1798208981..cb1ca668a7 100644 --- a/libraries/render/src/render/Args.h +++ b/libraries/render/src/render/Args.h @@ -136,7 +136,7 @@ namespace render { render::ScenePointer _scene; int8_t _cameraMode { -1 }; - std::function _hudOperator { nullptr }; + std::function _hudOperator { nullptr }; gpu::TexturePointer _hudTexture { nullptr }; bool _takingSnapshot { false }; diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index 4736359832..6b66e844c0 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -614,7 +614,7 @@ public: virtual ShapeKey getShapeKey() = 0; virtual Item::Bound getBound() = 0; virtual void render(RenderArgs* args) = 0; - virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) = 0; + virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) const = 0; }; template <> const ItemKey payloadGetKey(const PayloadProxyInterface::Pointer& payload); diff --git a/libraries/render/src/render/RenderFetchCullSortTask.cpp b/libraries/render/src/render/RenderFetchCullSortTask.cpp index d82fdef258..6b1a57ed88 100644 --- a/libraries/render/src/render/RenderFetchCullSortTask.cpp +++ b/libraries/render/src/render/RenderFetchCullSortTask.cpp @@ -30,7 +30,7 @@ void RenderFetchCullSortTask::build(JobModel& task, const Varying& input, Varyin const auto culledSpatialSelection = task.addJob("CullSceneSelection", cullInputs, cullFunctor, RenderDetails::ITEM); // Layered objects are not culled - const ItemFilter layeredFilter = ItemFilter::Builder().withVisible().withoutSubMetaCulled().withTagBits(tagBits, tagMask); + const ItemFilter layeredFilter = ItemFilter::Builder::visibleWorldItems().withTagBits(tagBits, tagMask); const auto nonspatialFilter = render::Varying(layeredFilter); const auto nonspatialSelection = task.addJob("FetchLayeredSelection", nonspatialFilter); diff --git a/libraries/render/src/render/ResampleTask.cpp b/libraries/render/src/render/ResampleTask.cpp index 3e9bfec8da..b3d4b38d02 100644 --- a/libraries/render/src/render/ResampleTask.cpp +++ b/libraries/render/src/render/ResampleTask.cpp @@ -16,6 +16,7 @@ #include using namespace render; +using namespace shader::gpu::program; gpu::PipelinePointer HalfDownsample::_pipeline; @@ -137,6 +138,7 @@ void Upsample::run(const RenderContextPointer& renderContext, const gpu::Framebu } gpu::PipelinePointer UpsampleToBlitFramebuffer::_pipeline; +gpu::PipelinePointer UpsampleToBlitFramebuffer::_mirrorPipeline; void UpsampleToBlitFramebuffer::run(const RenderContextPointer& renderContext, const Input& input, gpu::FramebufferPointer& resampledFrameBuffer) { assert(renderContext->args); @@ -148,10 +150,11 @@ void UpsampleToBlitFramebuffer::run(const RenderContextPointer& renderContext, c if (resampledFrameBuffer != sourceFramebuffer) { if (!_pipeline) { - gpu::ShaderPointer program = gpu::Shader::createProgram(shader::gpu::program::drawTransformUnitQuadTextureOpaque); gpu::StatePointer state = gpu::StatePointer(new gpu::State()); state->setDepthTest(gpu::State::DepthTest(false, false)); - _pipeline = gpu::Pipeline::create(program, state); + + _pipeline = gpu::Pipeline::create(gpu::Shader::createProgram(drawTransformUnitQuadTextureOpaque), state); + _mirrorPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTextureMirroredX), state); } const auto bufferSize = resampledFrameBuffer->getSize(); glm::ivec4 viewport{ 0, 0, bufferSize.x, bufferSize.y }; @@ -164,7 +167,7 @@ void UpsampleToBlitFramebuffer::run(const RenderContextPointer& renderContext, c batch.setViewportTransform(viewport); batch.setProjectionTransform(glm::mat4()); batch.resetViewTransform(); - batch.setPipeline(_pipeline); + batch.setPipeline(args->_renderMode == RenderArgs::MIRROR_RENDER_MODE ? _mirrorPipeline : _pipeline); batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(bufferSize, viewport)); batch.setResourceTexture(0, sourceFramebuffer->getRenderBuffer(0)); diff --git a/libraries/render/src/render/ResampleTask.h b/libraries/render/src/render/ResampleTask.h index e62b76e6d0..92f720c843 100644 --- a/libraries/render/src/render/ResampleTask.h +++ b/libraries/render/src/render/ResampleTask.h @@ -80,6 +80,7 @@ namespace render { protected: static gpu::PipelinePointer _pipeline; + static gpu::PipelinePointer _mirrorPipeline; }; } diff --git a/libraries/render/src/render/ShapePipeline.cpp b/libraries/render/src/render/ShapePipeline.cpp index 21af30c584..12947f5291 100644 --- a/libraries/render/src/render/ShapePipeline.cpp +++ b/libraries/render/src/render/ShapePipeline.cpp @@ -104,7 +104,7 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p locations->fadeMaskTextureUnit = reflection.validTexture(render_utils::slot::texture::FadeMask); locations->fadeParameterBufferUnit = reflection.validUniformBuffer(render_utils::slot::buffer::FadeParameters); locations->fadeObjectParameterBufferUnit = reflection.validUniformBuffer(render_utils::slot::buffer::FadeObjectParameters); - locations->hazeParameterBufferUnit = reflection.validUniformBuffer(render_utils::slot::buffer::HazeParams); + locations->hazeParameterBufferUnit = reflection.validUniformBuffer(graphics::slot::buffer::HazeParams); if (key.isTranslucent()) { locations->lightClusterGridBufferUnit = reflection.validUniformBuffer(render_utils::slot::buffer::LightClusterGrid); locations->lightClusterContentBufferUnit = reflection.validUniformBuffer(render_utils::slot::buffer::LightClusterContent); @@ -134,7 +134,7 @@ const ShapePipelinePointer ShapePlumber::pickPipeline(RenderArgs* args, const Ke auto factoryIt = ShapePipeline::_globalCustomFactoryMap.find(key.getCustom()); if ((factoryIt != ShapePipeline::_globalCustomFactoryMap.end()) && (factoryIt)->second) { // found a factory for the custom key, can now generate a shape pipeline for this case: - addPipelineHelper(Filter(key), key, 0, (factoryIt)->second(*this, key, *(args->_batch))); + addPipelineHelper(Filter(key), key, 0, (factoryIt)->second(*this, key, args)); return pickPipeline(args, key); } else { diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index ad91ea61ef..cf41c85dd9 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -272,7 +272,7 @@ protected: ItemSetter _itemSetter; public: using CustomKey = uint8_t; - using CustomFactory = std::function (const ShapePlumber& plumber, const ShapeKey& key, gpu::Batch& batch)>; + using CustomFactory = std::function (const ShapePlumber& plumber, const ShapeKey& key, RenderArgs* args)>; using CustomFactoryMap = std::map; static CustomFactoryMap _globalCustomFactoryMap; diff --git a/libraries/script-engine/src/AudioScriptingInterface.h b/libraries/script-engine/src/AudioScriptingInterface.h index dea44d6a1d..10af9214c1 100644 --- a/libraries/script-engine/src/AudioScriptingInterface.h +++ b/libraries/script-engine/src/AudioScriptingInterface.h @@ -108,8 +108,8 @@ public: * Sets whether your microphone audio is echoed back to you from the server. When enabled, microphone audio is echoed * only if you're unmuted or are using push-to-talk. * @function Audio.setServerEcho - * @parm {boolean} serverEcho - true to enable echoing microphone back to you from the server, - * false to disable. + * @param {boolean} serverEcho - true to enable echoing microphone back to you from the server, + * false to disable. */ Q_INVOKABLE void setServerEcho(bool serverEcho); diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 02dcde3695..5e20f06a7f 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -224,7 +224,7 @@ ScriptEngine::ScriptEngine(Context context, const QString& scriptContents, const if (_type == Type::ENTITY_CLIENT || _type == Type::ENTITY_SERVER) { QObject::connect(this, &ScriptEngine::update, this, [this]() { // process pending entity script content - if (!_contentAvailableQueue.empty()) { + if (!_contentAvailableQueue.empty() && !(_isFinished || _isStopping)) { EntityScriptContentAvailableMap pending; std::swap(_contentAvailableQueue, pending); for (auto& pair : pending) { @@ -343,7 +343,7 @@ void ScriptEngine::runDebuggable() { // we check for 'now' in the past in case people set their clock back if (_lastUpdate < now) { float deltaTime = (float)(now - _lastUpdate) / (float)USECS_PER_SECOND; - if (!_isFinished) { + if (!(_isFinished || _isStopping)) { emit update(deltaTime); } } @@ -411,6 +411,27 @@ void ScriptEngine::waitTillDoneRunning() { // We should never be waiting (blocking) on our own thread assert(workerThread != QThread::currentThread()); +#ifdef Q_OS_MAC + // On mac, don't call QCoreApplication::processEvents() here. This is to prevent + // [NSApplication terminate:] from prematurely destroying the static destructors + // while we are waiting for the scripts to shutdown. We will pump the message + // queue later in the Application destructor. + if (workerThread->isRunning()) { + workerThread->quit(); + + if (isEvaluating()) { + qCWarning(scriptengine) << "Script Engine has been running too long, aborting:" << getFilename(); + abortEvaluation(); + } + + // Wait for the scripting thread to stop running, as + // flooding it with aborts/exceptions will persist it longer + static const auto MAX_SCRIPT_QUITTING_TIME = 0.5 * MSECS_PER_SECOND; + if (!workerThread->wait(MAX_SCRIPT_QUITTING_TIME)) { + workerThread->terminate(); + } + } +#else auto startedWaiting = usecTimestampNow(); while (workerThread->isRunning()) { // If the final evaluation takes too long, then tell the script engine to stop running @@ -448,6 +469,7 @@ void ScriptEngine::waitTillDoneRunning() { // Avoid a pure busy wait QThread::yieldCurrentThread(); } +#endif scriptInfoMessage("Script Engine has stopped:" + getFilename()); } diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index 17f2aea9a5..f94fca3463 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -29,6 +29,7 @@ static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStanda static const bool HIFI_SCRIPT_DEBUGGABLES { true }; static const QString SETTINGS_KEY { "RunningScripts" }; static const QUrl DEFAULT_SCRIPTS_LOCATION { "file:///~//defaultScripts.js" }; + // Using a QVariantList so this is human-readable in the settings file static Setting::Handle runningScriptsHandle(SETTINGS_KEY, { QVariant(DEFAULT_SCRIPTS_LOCATION) }); @@ -64,8 +65,8 @@ void ScriptEngines::onErrorLoadingScript(const QString& url) { emit errorLoadingScript(url); } -ScriptEngines::ScriptEngines(ScriptEngine::Context context) - : _context(context) +ScriptEngines::ScriptEngines(ScriptEngine::Context context, const QUrl& defaultScriptsOverride) + : _context(context), _defaultScriptsOverride(defaultScriptsOverride) { _scriptsModelFilter.setSourceModel(&_scriptsModel); _scriptsModelFilter.sort(0, Qt::AscendingOrder); @@ -322,13 +323,22 @@ void ScriptEngines::loadScripts() { // loads all saved scripts auto runningScripts = runningScriptsHandle.get(); + bool defaultScriptsOverrideSet = !_defaultScriptsOverride.isEmpty(); for (auto script : runningScripts) { - auto string = script.toString(); - if (!string.isEmpty()) { - loadScript(string); + auto url = script.toUrl(); + if (!url.isEmpty()) { + if (defaultScriptsOverrideSet && url == DEFAULT_SCRIPTS_LOCATION) { + _defaultScriptsWasRunning = true; + } else { + loadScript(url); + } } } + + if (defaultScriptsOverrideSet) { + loadScript(_defaultScriptsOverride, false); + } } void ScriptEngines::saveScripts() { @@ -359,6 +369,10 @@ void ScriptEngines::saveScripts() { } } + if (_defaultScriptsWasRunning) { + list.append(DEFAULT_SCRIPTS_LOCATION); + } + runningScriptsHandle.set(list); } diff --git a/libraries/script-engine/src/ScriptEngines.h b/libraries/script-engine/src/ScriptEngines.h index 4db150fce5..de836a3e09 100644 --- a/libraries/script-engine/src/ScriptEngines.h +++ b/libraries/script-engine/src/ScriptEngines.h @@ -56,7 +56,7 @@ class ScriptEngines : public QObject, public Dependency { public: using ScriptInitializer = ScriptInitializerMixin::ScriptInitializer; - ScriptEngines(ScriptEngine::Context context); + ScriptEngines(ScriptEngine::Context context, const QUrl& defaultScriptsOverride = QUrl()); void registerScriptInitializer(ScriptInitializer initializer); int runScriptInitializers(ScriptEnginePointer engine); void loadScripts(); @@ -284,6 +284,12 @@ protected: std::atomic _isReloading { false }; bool _defaultScriptsLocationOverridden { false }; QString _debugScriptUrl; + + // If this is set, defaultScripts.js will not be run if it is in the settings, + // and this will be run instead. This script will not be persisted to settings. + const QUrl _defaultScriptsOverride { }; + // If an override is set, this will be true if defaultScripts.js was previously running. + bool _defaultScriptsWasRunning { false }; }; QUrl normalizeScriptURL(const QUrl& rawScriptURL); diff --git a/libraries/shared/src/shared/ConicalViewFrustum.cpp b/libraries/shared/src/shared/ConicalViewFrustum.cpp index 78f4f7d1bc..34f7ea793a 100644 --- a/libraries/shared/src/shared/ConicalViewFrustum.cpp +++ b/libraries/shared/src/shared/ConicalViewFrustum.cpp @@ -145,7 +145,8 @@ int ConicalViewFrustum::deserialize(const unsigned char* sourceBuffer) { return sourceBuffer - startPosition; } -void ConicalViewFrustum::setSimpleRadius(float radius) { +void ConicalViewFrustum::setPositionAndSimpleRadius(const glm::vec3& position, float radius) { + _position = position; _radius = radius; _farClip = radius / 2.0f; } diff --git a/libraries/shared/src/shared/ConicalViewFrustum.h b/libraries/shared/src/shared/ConicalViewFrustum.h index 6a2cc53f03..8879c360a2 100644 --- a/libraries/shared/src/shared/ConicalViewFrustum.h +++ b/libraries/shared/src/shared/ConicalViewFrustum.h @@ -55,7 +55,7 @@ public: int deserialize(const unsigned char* sourceBuffer); // Just test for within radius. - void setSimpleRadius(float radius); + void setPositionAndSimpleRadius(const glm::vec3& position, float radius); private: glm::vec3 _position { 0.0f, 0.0f, 0.0f }; diff --git a/plugins/oculus/src/OculusDisplayPlugin.cpp b/plugins/oculus/src/OculusDisplayPlugin.cpp index f928ccb8a4..bd0c77ae57 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusDisplayPlugin.cpp @@ -124,15 +124,6 @@ void OculusDisplayPlugin::uncustomizeContext() { Parent::uncustomizeContext(); } -gpu::PipelinePointer OculusDisplayPlugin::getRenderTexturePipeline() { - //return _SRGBToLinearPipeline; - return _drawTexturePipeline; -} - -gpu::PipelinePointer OculusDisplayPlugin::getCompositeScenePipeline() { - return _SRGBToLinearPipeline; -} - static const uint64_t FRAME_BUDGET = (11 * USECS_PER_MSEC); static const uint64_t FRAME_OVER_BUDGET = (15 * USECS_PER_MSEC); diff --git a/plugins/oculus/src/OculusDisplayPlugin.h b/plugins/oculus/src/OculusDisplayPlugin.h index a892d27534..9209fd373e 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.h +++ b/plugins/oculus/src/OculusDisplayPlugin.h @@ -24,9 +24,6 @@ public: virtual QJsonObject getHardwareStats() const; - virtual gpu::PipelinePointer getRenderTexturePipeline() override; - virtual gpu::PipelinePointer getCompositeScenePipeline() override; - protected: QThread::Priority getPresentPriority() override { return QThread::TimeCriticalPriority; } diff --git a/script-archive/example/ui/MyEnergyBar.js b/script-archive/example/ui/MyEnergyBar.js index 2d01a66317..98fb35814c 100644 --- a/script-archive/example/ui/MyEnergyBar.js +++ b/script-archive/example/ui/MyEnergyBar.js @@ -33,14 +33,14 @@ var bar = Overlays.addOverlay("text", { // Takes an energy value between 0 and 1 and sets energy bar width appropriately function setEnergy(energy) { - energy = clamp(energy, 0, 1); + energy = hifiClamp(energy, 0, 1); var barWidth = totalWidth * energy; var color = energy <= lowEnergyThreshold ? lowEnergyColor: energyColor; Overlays.editOverlay(bar, { width: barWidth, backgroundColor: color}); } function update() { - currentEnergy = clamp(MyAvatar.energy, 0, 1); + currentEnergy = hifiClamp(MyAvatar.energy, 0, 1); setEnergy(currentEnergy); } diff --git a/script-archive/example/ui/energyBar.js b/script-archive/example/ui/energyBar.js index 498eef2751..6a97f88472 100644 --- a/script-archive/example/ui/energyBar.js +++ b/script-archive/example/ui/energyBar.js @@ -45,14 +45,14 @@ var bar = Overlays.addOverlay("text", { // Takes an energy value between 0 and 1 and sets energy bar width appropriately function setEnergy(energy) { - energy = clamp(energy, 0, 1); + energy = hifiClamp(energy, 0, 1); var barWidth = totalWidth * energy; var color = energy <= lowEnergyThreshold ? lowEnergyColor: energyColor; Overlays.editOverlay(bar, { width: barWidth, backgroundColor: color}); } function update() { - currentEnergy = clamp(MyAvatar.energy, 0, 1); + currentEnergy = hifiClamp(MyAvatar.energy, 0, 1); setEnergy(currentEnergy); } diff --git a/script-archive/light_modifier/README.md b/script-archive/light_modifier/README.md index f23bd25dda..d78fe3ef41 100644 --- a/script-archive/light_modifier/README.md +++ b/script-archive/light_modifier/README.md @@ -18,7 +18,7 @@ When you run the lightLoader.js script, several scripts will be loaded: - visiblePanel.js (the transparent panel) - closeButton.js (for closing the ui) - ../libraries/lightOverlayManager.js (shows 2d overlays for lights in the world) -- ../libraries/entitySelectionTool.js (visualizes volume of the lights) +- ../../scripts/system/create/entitySelectionTool/entitySelectionTool.js (visualizes volume of the lights) Current sliders are (top to bottom): red diff --git a/script-archive/light_modifier/lightModifier.js b/script-archive/light_modifier/lightModifier.js index 0c691e2b2e..35cdfb95ce 100644 --- a/script-archive/light_modifier/lightModifier.js +++ b/script-archive/light_modifier/lightModifier.js @@ -33,8 +33,8 @@ var PARENT_SCRIPT_URL = Script.resolvePath('lightParent.js?' + Math.random(0 - 1 if (SHOW_OVERLAYS === true) { - Script.include('../libraries/gridTool.js'); - Script.include('../libraries/entitySelectionTool.js?' + Math.random(0 - 100)); + Script.include('../../scripts/system/libraries/gridTool.js'); + Script.include('../../scripts/system/create/entitySelectionTool/entitySelectionTool.js?' + Math.random(0 - 100)); Script.include('../libraries/lightOverlayManager.js'); var grid = Grid(); diff --git a/scripts/defaultScripts.js b/scripts/defaultScripts.js index e392680df9..6f0dd40493 100644 --- a/scripts/defaultScripts.js +++ b/scripts/defaultScripts.js @@ -27,16 +27,17 @@ var DEFAULT_SCRIPTS_COMBINED = [ "system/marketplaces/marketplaces.js", "system/notifications.js", "system/commerce/wallet.js", - "system/edit.js", + "system/create/edit.js", "system/dialTone.js", "system/firstPersonHMD.js", "system/tablet-ui/tabletUI.js", "system/emote.js", "system/miniTablet.js", - "system/audioMuteOverlay.js" + "system/audioMuteOverlay.js", + "system/keyboardShortcuts/keyboardShortcuts.js" ]; var DEFAULT_SCRIPTS_SEPARATE = [ - "system/controllers/controllerScripts.js", + "system/controllers/controllerScripts.js" //"system/chat.js" ]; diff --git a/scripts/developer/tests/interactiveWindowTest.js b/scripts/developer/tests/interactiveWindowTest.js index c17deba617..16388d52c0 100644 --- a/scripts/developer/tests/interactiveWindowTest.js +++ b/scripts/developer/tests/interactiveWindowTest.js @@ -19,7 +19,7 @@ function getPreferredTitle() { var virtualWindow = Desktop.createWindow(Script.resourcesPath() + 'qml/OverlayWindowTest.qml', { title: getPreferredTitle(), - flags: Desktop.ALWAYS_ON_TOP, + additionalFlags: Desktop.ALWAYS_ON_TOP, presentationMode: getPreferredPresentationMode(), size: {x: 500, y: 400} }); diff --git a/scripts/developer/utilities/lib/prop/PropGroup.qml b/scripts/developer/utilities/lib/prop/PropGroup.qml index 848ff8b288..c6b2c694f6 100644 --- a/scripts/developer/utilities/lib/prop/PropGroup.qml +++ b/scripts/developer/utilities/lib/prop/PropGroup.qml @@ -86,19 +86,30 @@ PropFolderPanel { var itemLabel = proItem.property; var itemDepth = root.indentDepth + 1; if (Array.isArray(itemRootObject)) { - if (objectItem.length > 1) { - itemLabel = itemLabel + " " + objectItem.length + itemLabel = proItem.property + "[] / " + itemRootObject.length + if (itemRootObject.length == 0) { + var component = Qt.createComponent("PropItem.qml"); + component.createObject(propItemsContainer, { + "label": itemLabel + }) } else { - itemLabel = itemLabel + " " + objectItem.length - itemRootObject = itemRootObject[0]; + var component = Qt.createComponent("PropGroup.qml"); + component.createObject(propItemsContainer, { + "label": itemLabel, + "rootObject":itemRootObject, + "indentDepth": itemDepth, + "isUnfold": true, + }) } + } else { + var component = Qt.createComponent("PropGroup.qml"); + component.createObject(propItemsContainer, { + "label": itemLabel, + "rootObject":itemRootObject, + "indentDepth": itemDepth, + "isUnfold": true, + }) } - var component = Qt.createComponent("PropGroup.qml"); - component.createObject(propItemsContainer, { - "label": itemLabel, - "rootObject":itemRootObject, - "indentDepth": itemDepth, - }) } break; case 'printLabel': { var component = Qt.createComponent("PropItem.qml"); @@ -125,12 +136,6 @@ PropFolderPanel { function populateFromObjectProps(object) { var propsModel = [] - if (Array.isArray(object)) { - if (object.length <= 1) { - object = object[0]; - } - } - var props = Object.keys(object); for (var p in props) { var o = {}; diff --git a/scripts/developer/utilities/render/engineProfiler.js b/scripts/developer/utilities/render/engineProfiler.js index 418cab8622..88ab388c75 100644 --- a/scripts/developer/utilities/render/engineProfiler.js +++ b/scripts/developer/utilities/render/engineProfiler.js @@ -36,7 +36,7 @@ var qml = Script.resolvePath(QMLAPP_URL); window = Desktop.createWindow(Script.resolvePath(QMLAPP_URL), { title: 'Render Engine Profiler', - flags: Desktop.ALWAYS_ON_TOP, + additionalFlags: Desktop.ALWAYS_ON_TOP, presentationMode: Desktop.PresentationMode.NATIVE, size: {x: 500, y: 100} }); diff --git a/scripts/developer/utilities/render/lod.js b/scripts/developer/utilities/render/lod.js index f3e4208034..ba8cbf65f8 100644 --- a/scripts/developer/utilities/render/lod.js +++ b/scripts/developer/utilities/render/lod.js @@ -52,7 +52,7 @@ var qml = Script.resolvePath(QMLAPP_URL); window = Desktop.createWindow(Script.resolvePath(QMLAPP_URL), { title: TABLET_BUTTON_NAME, - flags: Desktop.ALWAYS_ON_TOP, + additionalFlags: Desktop.ALWAYS_ON_TOP, presentationMode: Desktop.PresentationMode.NATIVE, size: {x: 400, y: 600} }); diff --git a/scripts/developer/utilities/render/performanceSetup.qml b/scripts/developer/utilities/render/performanceSetup.qml index 4654736f72..be9b6a3271 100644 --- a/scripts/developer/utilities/render/performanceSetup.qml +++ b/scripts/developer/utilities/render/performanceSetup.qml @@ -51,6 +51,7 @@ Rectangle { } Prop.PropFolderPanel { label: "Platform" + isUnfold: true panelFrameData: Component { Platform { } diff --git a/scripts/developer/utilities/render/shadow.qml b/scripts/developer/utilities/render/shadow.qml old mode 100644 new mode 100755 index a1d6777a68..427b52c659 --- a/scripts/developer/utilities/render/shadow.qml +++ b/scripts/developer/utilities/render/shadow.qml @@ -67,7 +67,7 @@ Rectangle { } ColumnLayout { - spacing: 20 + spacing: 10 anchors.left: parent.left anchors.right: parent.right anchors.margins: hifi.dimensions.contentMargin.x @@ -109,6 +109,26 @@ Rectangle { font.italic: true } } + ConfigSlider { + label: qsTr("Bias Input") + integral: false + config: shadowConfig + property: "biasInput" + max: 1.0 + min: 0.0 + height: 38 + width:250 + } + ConfigSlider { + label: qsTr("Shadow Max Distance") + integral: false + config: shadowConfig + property: "globalMaxDistance" + max: 100.0 + min: 1.0 + height: 38 + width:250 + } Repeater { model: [ "0", "1", "2", "3" diff --git a/scripts/developer/utilities/workload/avatars.js b/scripts/developer/utilities/workload/avatars.js index 3080ef09db..c0aaec9b43 100644 --- a/scripts/developer/utilities/workload/avatars.js +++ b/scripts/developer/utilities/workload/avatars.js @@ -52,7 +52,7 @@ var qml = Script.resolvePath(QMLAPP_URL); window = Desktop.createWindow(Script.resolvePath(QMLAPP_URL), { title: TABLET_BUTTON_NAME, - flags: Desktop.ALWAYS_ON_TOP, + additionalFlags: Desktop.ALWAYS_ON_TOP, presentationMode: Desktop.PresentationMode.NATIVE, size: {x: 400, y: 600} }); diff --git a/scripts/developer/utilities/workload/workload.js b/scripts/developer/utilities/workload/workload.js index ada3cbbf09..8871936a95 100644 --- a/scripts/developer/utilities/workload/workload.js +++ b/scripts/developer/utilities/workload/workload.js @@ -52,7 +52,7 @@ var qml = Script.resolvePath(QMLAPP_URL); window = Desktop.createWindow(Script.resolvePath(QMLAPP_URL), { title: 'Workload Inspector', - flags: Desktop.ALWAYS_ON_TOP, + additionalFlags: Desktop.ALWAYS_ON_TOP, presentationMode: Desktop.PresentationMode.NATIVE, size: {x: 400, y: 600} }); diff --git a/scripts/simplifiedUI/defaultScripts.js b/scripts/simplifiedUI/defaultScripts.js deleted file mode 100644 index ccefcc3a95..0000000000 --- a/scripts/simplifiedUI/defaultScripts.js +++ /dev/null @@ -1,39 +0,0 @@ -"use strict"; -/* jslint vars: true, plusplus: true */ - -// -// defaultScripts.js -// -// Authors: Zach Fox -// Created: 2019-05-23 -// Copyright 2019 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 -// - -var DEFAULT_SCRIPTS_SEPARATE = [ - "system/controllers/controllerScripts.js", - "ui/simplifiedUI.js" -]; -function loadSeparateDefaults() { - for (var i in DEFAULT_SCRIPTS_SEPARATE) { - Script.load(DEFAULT_SCRIPTS_SEPARATE[i]); - } -} - - -var DEFAULT_SCRIPTS_COMBINED = [ - "system/request-service.js", - "system/progress.js", - "system/away.js" -]; -function runDefaultsTogether() { - for (var i in DEFAULT_SCRIPTS_COMBINED) { - Script.include(DEFAULT_SCRIPTS_COMBINED[i]); - } - loadSeparateDefaults(); -} - - -runDefaultsTogether(); diff --git a/scripts/simplifiedUI/modules/appUi.js b/scripts/simplifiedUI/modules/appUi.js deleted file mode 100644 index 9771348377..0000000000 --- a/scripts/simplifiedUI/modules/appUi.js +++ /dev/null @@ -1,387 +0,0 @@ -"use strict"; -/* global Tablet, Script */ -// -// libraries/appUi.js -// -// Created by Howard Stearns on 3/20/18. -// Copyright 2018 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 -// - -function AppUi(properties) { - var request = Script.require('request').request; - /* Example development order: - 1. var AppUi = Script.require('appUi'); - 2. Put appname-i.svg, appname-a.svg in graphicsDirectory (where non-default graphicsDirectory can be added in #3). - 3. ui = new AppUi({buttonName: "APPNAME", home: "qml-or-html-path"}); - (And if converting an existing app, - define var tablet = ui.tablet, button = ui.button; as needed. - remove button.clicked.[dis]connect and tablet.remove(button).) - 4. Define onOpened and onClosed behavior in #3, if any. - (And if converting an existing app, remove screenChanged.[dis]connect.) - 5. Define onMessage and sendMessage in #3, if any. onMessage is wired/unwired on open/close. If you - want a handler to be "always on", connect it yourself at script startup. - (And if converting an existing app, remove code that [un]wires that message handling such as - fromQml/sendToQml or webEventReceived/emitScriptEvent.) - 6. (If converting an existing app, cleanup stuff that is no longer necessary, like references to button, tablet, - and use isOpen, open(), and close() as needed.) - 7. lint! - */ - var that = this; - function defaultButton(name, suffix) { - var base = that[name] || (that.buttonPrefix + suffix); - that[name] = (base.indexOf('/') >= 0) ? base : (that.graphicsDirectory + base); // poor man's merge - } - - // Defaults: - that.tabletName = "com.highfidelity.interface.tablet.system"; - that.inject = ""; - that.graphicsDirectory = "icons/tablet-icons/"; // Where to look for button svgs. See below. - that.additionalAppScreens = []; - that.checkIsOpen = function checkIsOpen(type, tabletUrl) { // Are we active? Value used to set isOpen. - // Actual url may have prefix or suffix. - return that.currentVisibleUrl && - ((that.home.indexOf(that.currentVisibleUrl) > -1) || - (that.additionalAppScreens.indexOf(that.currentVisibleUrl) > -1)); - }; - that.setCurrentVisibleScreenMetadata = function setCurrentVisibleScreenMetadata(type, url) { - that.currentVisibleScreenType = type; - that.currentVisibleUrl = url; - }; - that.open = function open(optionalUrl, optionalInject) { // How to open the app. - var url = optionalUrl || that.home; - var inject = optionalInject || that.inject; - - if (that.isQMLUrl(url)) { - that.tablet.loadQMLSource(url); - } else { - that.tablet.gotoWebScreen(url, inject); - } - }; - // Opens some app on top of the current app (on desktop, opens new window) - that.openNewAppOnTop = function openNewAppOnTop(url, optionalInject) { - var inject = optionalInject || ""; - if (that.isQMLUrl(url)) { - that.tablet.loadQMLOnTop(url); - } else { - that.tablet.loadWebScreenOnTop(url, inject); - } - }; - that.close = function close() { // How to close the app. - that.currentVisibleUrl = ""; - // for toolbar-mode: go back to home screen, this will close the window. - that.tablet.gotoHomeScreen(); - }; - that.buttonActive = function buttonActive(isActive) { // How to make the button active (white). - that.button.editProperties({isActive: isActive}); - }; - that.isQMLUrl = function isQMLUrl(url) { - var type = /.qml$/.test(url) ? 'QML' : 'Web'; - return type === 'QML'; - }; - that.isCurrentlyOnQMLScreen = function isCurrentlyOnQMLScreen() { - return that.currentVisibleScreenType === 'QML'; - }; - - // - // START Notification Handling Defaults - // - that.messagesWaiting = function messagesWaiting(isWaiting) { // How to indicate a message light on button. - // Note that waitingButton doesn't have to exist unless someone explicitly calls this with isWaiting true. - that.button.editProperties({ - icon: isWaiting ? that.normalMessagesButton : that.normalButton, - activeIcon: isWaiting ? that.activeMessagesButton : that.activeButton - }); - }; - that.notificationPollTimeout = [false]; - that.notificationPollTimeoutMs = [60000]; - that.notificationPollEndpoint = [false]; - that.notificationPollStopPaginatingConditionMet = [false]; - that.notificationDataProcessPage = function (data) { - return data; - }; - that.notificationPollCallback = [that.ignore]; - that.notificationPollCaresAboutSince = [false]; - that.notificationInitialCallbackMade = [false]; - that.notificationDisplayBanner = function (message) { - if (!that.isOpen) { - Window.displayAnnouncement(message); - } - }; - // - // END Notification Handling Defaults - // - - // Handlers - that.onScreenChanged = function onScreenChanged(type, url) { - // Set isOpen, wireEventBridge, set buttonActive as appropriate, - // and finally call onOpened() or onClosed() IFF defined. - that.setCurrentVisibleScreenMetadata(type, url); - - if (that.checkIsOpen(type, url)) { - that.wireEventBridge(true); - if (!that.isOpen) { - that.buttonActive(true); - if (that.onOpened) { - that.onOpened(); - } - that.isOpen = true; - } - } else { - // A different screen is now visible, or the tablet has been closed. - // Tablet visibility is controlled separately by `tabletShownChanged()` - that.wireEventBridge(false); - if (that.isOpen) { - that.buttonActive(false); - if (that.onClosed) { - that.onClosed(); - } - that.isOpen = false; - } - } - }; - - // Overwrite with the given properties: - Object.keys(properties).forEach(function (key) { - that[key] = properties[key]; - }); - - // - // START Notification Handling - // - - var currentDataPageToRetrieve = []; - var concatenatedServerResponse = []; - for (var i = 0; i < that.notificationPollEndpoint.length; i++) { - currentDataPageToRetrieve[i] = 1; - concatenatedServerResponse[i] = new Array(); - } - - var MAX_LOG_LENGTH_CHARACTERS = 300; - function requestCallback(error, response, optionalParams) { - var indexOfRequest = optionalParams.indexOfRequest; - var urlOfRequest = optionalParams.urlOfRequest; - - if (error || (response.status !== 'success')) { - print("Error: unable to complete request from URL. Error:", error || response.status); - startNotificationTimer(indexOfRequest); - return; - } - - if (!that.notificationPollStopPaginatingConditionMet[indexOfRequest] || - that.notificationPollStopPaginatingConditionMet[indexOfRequest](response)) { - startNotificationTimer(indexOfRequest); - - var notificationData; - if (concatenatedServerResponse[indexOfRequest].length) { - notificationData = concatenatedServerResponse[indexOfRequest]; - } else { - notificationData = that.notificationDataProcessPage[indexOfRequest](response); - } - console.debug(that.buttonName, - 'truncated notification data for processing:', - JSON.stringify(notificationData).substring(0, MAX_LOG_LENGTH_CHARACTERS)); - that.notificationPollCallback[indexOfRequest](notificationData); - that.notificationInitialCallbackMade[indexOfRequest] = true; - currentDataPageToRetrieve[indexOfRequest] = 1; - concatenatedServerResponse[indexOfRequest] = new Array(); - } else { - concatenatedServerResponse[indexOfRequest] = - concatenatedServerResponse[indexOfRequest].concat(that.notificationDataProcessPage[indexOfRequest](response)); - currentDataPageToRetrieve[indexOfRequest]++; - request({ - json: true, - uri: (urlOfRequest + "&page=" + currentDataPageToRetrieve[indexOfRequest]) - }, requestCallback, optionalParams); - } - } - - - var METAVERSE_BASE = Account.metaverseServerURL; - var MS_IN_SEC = 1000; - that.notificationPoll = function (i) { - if (!that.notificationPollEndpoint[i]) { - return; - } - - // User is "appearing offline" or is not logged in - if (GlobalServices.findableBy === "none" || Account.username === "Unknown user") { - // The notification polling will restart when the user changes their availability - // or when they log in, so it's not necessary to restart a timer here. - console.debug(that.buttonName + " Notifications: User is appearing offline or not logged in. " + - that.buttonName + " will poll for notifications when user logs in and has their availability " + - "set to not appear offline."); - return; - } - - var url = METAVERSE_BASE + that.notificationPollEndpoint[i]; - - var settingsKey = "notifications/" + that.notificationPollEndpoint[i] + "/lastPoll"; - var currentTimestamp = new Date().getTime(); - var lastPollTimestamp = Settings.getValue(settingsKey, currentTimestamp); - if (that.notificationPollCaresAboutSince[i]) { - url = url + "&since=" + lastPollTimestamp / MS_IN_SEC; - } - Settings.setValue(settingsKey, currentTimestamp); - - request({ - json: true, - uri: url - }, - requestCallback, - { - indexOfRequest: i, - urlOfRequest: url - }); - }; - - // This won't do anything if there isn't a notification endpoint set - for (i = 0; i < that.notificationPollEndpoint.length; i++) { - that.notificationPoll(i); - } - - function startNotificationTimer(indexOfRequest) { - that.notificationPollTimeout[indexOfRequest] = Script.setTimeout(function () { - that.notificationPoll(indexOfRequest); - }, that.notificationPollTimeoutMs[indexOfRequest]); - } - - function restartNotificationPoll() { - for (var j = 0; j < that.notificationPollEndpoint.length; j++) { - that.notificationInitialCallbackMade[j] = false; - if (that.notificationPollTimeout[j]) { - Script.clearTimeout(that.notificationPollTimeout[j]); - that.notificationPollTimeout[j] = false; - } - that.notificationPoll(j); - } - } - // - // END Notification Handling - // - - // Properties: - that.tablet = Tablet.getTablet(that.tabletName); - // Must be after we gather properties. - that.buttonPrefix = that.buttonPrefix || that.buttonName.toLowerCase() + "-"; - defaultButton('normalButton', 'i.svg'); - defaultButton('activeButton', 'a.svg'); - defaultButton('normalMessagesButton', 'i-msg.svg'); - defaultButton('activeMessagesButton', 'a-msg.svg'); - var buttonOptions = { - icon: that.normalButton, - activeIcon: that.activeButton, - text: that.buttonName - }; - // `TabletScriptingInterface` looks for the presence of a `sortOrder` key. - // What it SHOULD do is look to see if the value inside that key is defined. - // To get around the current code, we do this instead. - if (that.sortOrder) { - buttonOptions.sortOrder = that.sortOrder; - } - that.button = that.tablet.addButton(buttonOptions); - that.ignore = function ignore() { }; - that.hasOutboundEventBridge = false; - that.hasInboundQmlEventBridge = false; - that.hasInboundHtmlEventBridge = false; - // HTML event bridge uses strings, not objects. Here we abstract over that. - // (Although injected javascript still has to use JSON.stringify/JSON.parse.) - that.sendToHtml = function (messageObject) { - that.tablet.emitScriptEvent(JSON.stringify(messageObject)); - }; - that.fromHtml = function (messageString) { - var parsedMessage = JSON.parse(messageString); - parsedMessage.messageSrc = "HTML"; - that.onMessage(parsedMessage); - }; - that.sendMessage = that.ignore; - that.wireEventBridge = function wireEventBridge(on) { - // Uniquivocally sets that.sendMessage(messageObject) to do the right thing. - // Sets has*EventBridge and wires onMessage to the proper event bridge as appropriate, IFF onMessage defined. - var isCurrentlyOnQMLScreen = that.isCurrentlyOnQMLScreen(); - // Outbound (always, regardless of whether there is an inbound handler). - if (on) { - that.sendMessage = isCurrentlyOnQMLScreen ? that.tablet.sendToQml : that.sendToHtml; - that.hasOutboundEventBridge = true; - } else { - that.sendMessage = that.ignore; - that.hasOutboundEventBridge = false; - } - - if (!that.onMessage) { - return; - } - - // Inbound - if (on) { - if (isCurrentlyOnQMLScreen && !that.hasInboundQmlEventBridge) { - console.debug(that.buttonName, 'connecting', that.tablet.fromQml); - that.tablet.fromQml.connect(that.onMessage); - that.hasInboundQmlEventBridge = true; - } else if (!isCurrentlyOnQMLScreen && !that.hasInboundHtmlEventBridge) { - console.debug(that.buttonName, 'connecting', that.tablet.webEventReceived); - that.tablet.webEventReceived.connect(that.fromHtml); - that.hasInboundHtmlEventBridge = true; - } - } else { - if (that.hasInboundQmlEventBridge) { - console.debug(that.buttonName, 'disconnecting', that.tablet.fromQml); - that.tablet.fromQml.disconnect(that.onMessage); - that.hasInboundQmlEventBridge = false; - } - if (that.hasInboundHtmlEventBridge) { - console.debug(that.buttonName, 'disconnecting', that.tablet.webEventReceived); - that.tablet.webEventReceived.disconnect(that.fromHtml); - that.hasInboundHtmlEventBridge = false; - } - } - }; - that.isOpen = false; - // To facilitate incremental development, only wire onClicked to do something when "home" is defined in properties. - that.onClicked = that.home - ? function onClicked() { - // Call open() or close(), and reset type based on current home property. - if (that.isOpen) { - that.close(); - } else { - that.open(); - } - } : that.ignore; - that.onScriptEnding = function onScriptEnding() { - // Close if necessary, clean up any remaining handlers, and remove the button. - GlobalServices.myUsernameChanged.disconnect(restartNotificationPoll); - GlobalServices.findableByChanged.disconnect(restartNotificationPoll); - that.tablet.screenChanged.disconnect(that.onScreenChanged); - if (that.isOpen) { - that.close(); - that.onScreenChanged("", ""); - } - if (that.button) { - if (that.onClicked) { - that.button.clicked.disconnect(that.onClicked); - } - that.tablet.removeButton(that.button); - } - for (var i = 0; i < that.notificationPollTimeout.length; i++) { - if (that.notificationPollTimeout[i]) { - Script.clearInterval(that.notificationPollTimeout[i]); - that.notificationPollTimeout[i] = false; - } - } - }; - // Set up the handlers. - that.tablet.screenChanged.connect(that.onScreenChanged); - that.button.clicked.connect(that.onClicked); - Script.scriptEnding.connect(that.onScriptEnding); - GlobalServices.findableByChanged.connect(restartNotificationPoll); - GlobalServices.myUsernameChanged.connect(restartNotificationPoll); - if (that.buttonName === Settings.getValue("startUpApp")) { - Settings.setValue("startUpApp", ""); - Script.setTimeout(function () { - that.open(); - }, 1000); - } -} -module.exports = AppUi; diff --git a/scripts/simplifiedUI/modules/request.js b/scripts/simplifiedUI/modules/request.js deleted file mode 100644 index 37f3ac0d7b..0000000000 --- a/scripts/simplifiedUI/modules/request.js +++ /dev/null @@ -1,83 +0,0 @@ -"use strict"; - -// request.js -// -// Created by Cisco Fresquet on 04/24/2017. -// Copyright 2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -/* global module */ -// @module request -// -// This module contains the `request` module implementation - -// =========================================================================================== -module.exports = { - - // ------------------------------------------------------------------ - // cb(error, responseOfCorrectContentType, optionalCallbackParameter) of url. A subset of npm request. - request: function (options, callback, optionalCallbackParameter) { - var httpRequest = new XMLHttpRequest(), key; - // QT bug: apparently doesn't handle onload. Workaround using readyState. - httpRequest.onreadystatechange = function () { - var READY_STATE_DONE = 4; - var HTTP_OK = 200; - if (httpRequest.readyState >= READY_STATE_DONE) { - var error = (httpRequest.status !== HTTP_OK) && httpRequest.status.toString() + ':' + httpRequest.statusText, - response = !error && httpRequest.responseText, - contentType = !error && httpRequest.getResponseHeader('content-type'); - if (!error && contentType.indexOf('application/json') === 0) { // ignoring charset, etc. - try { - response = JSON.parse(response); - } catch (e) { - error = e; - } - } - if (error) { - response = { statusCode: httpRequest.status }; - } - callback(error, response, optionalCallbackParameter); - } - }; - if (typeof options === 'string') { - options = { uri: options }; - } - if (options.url) { - options.uri = options.url; - } - if (!options.method) { - options.method = 'GET'; - } - if (options.body && (options.method === 'GET')) { // add query parameters - var params = [], appender = (-1 === options.uri.search('?')) ? '?' : '&'; - for (key in options.body) { - if (options.body.hasOwnProperty(key)) { - params.push(key + '=' + options.body[key]); - } - } - options.uri += appender + params.join('&'); - delete options.body; - } - if (options.json) { - options.headers = options.headers || {}; - options.headers["Content-type"] = "application/json"; - options.body = JSON.stringify(options.body); - } - for (key in options.headers || {}) { - if (options.headers.hasOwnProperty(key)) { - httpRequest.setRequestHeader(key, options.headers[key]); - } - } - httpRequest.open(options.method, options.uri, true); - httpRequest.send(options.body || null); - } -}; - -// =========================================================================================== -// @function - debug logging -function debug() { - print('RequestModule | ' + [].slice.call(arguments).join(' ')); -} diff --git a/scripts/simplifiedUI/modules/vec3.js b/scripts/simplifiedUI/modules/vec3.js deleted file mode 100644 index f164f01374..0000000000 --- a/scripts/simplifiedUI/modules/vec3.js +++ /dev/null @@ -1,69 +0,0 @@ -// Example of using a "system module" to decouple Vec3's implementation details. -// -// Users would bring Vec3 support in as a module: -// var vec3 = Script.require('vec3'); -// - -// (this example is compatible with using as a Script.include and as a Script.require module) -try { - // Script.require - module.exports = vec3; -} catch(e) { - // Script.include - Script.registerValue("vec3", vec3); -} - -vec3.fromObject = function(v) { - //return new vec3(v.x, v.y, v.z); - //... this is even faster and achieves the same effect - v.__proto__ = vec3.prototype; - return v; -}; - -vec3.prototype = { - multiply: function(v2) { - // later on could support overrides like so: - // if (v2 instanceof quat) { [...] } - // which of the below is faster (C++ or JS)? - // (dunno -- but could systematically find out and go with that version) - - // pure JS option - // return new vec3(this.x * v2.x, this.y * v2.y, this.z * v2.z); - - // hybrid C++ option - return vec3.fromObject(Vec3.multiply(this, v2)); - }, - // detects any NaN and Infinity values - isValid: function() { - return isFinite(this.x) && isFinite(this.y) && isFinite(this.z); - }, - // format Vec3's, eg: - // var v = vec3(); - // print(v); // outputs [Vec3 (0.000, 0.000, 0.000)] - toString: function() { - if (this === vec3.prototype) { - return "{Vec3 prototype}"; - } - function fixed(n) { return n.toFixed(3); } - return "[Vec3 (" + [this.x, this.y, this.z].map(fixed) + ")]"; - }, -}; - -vec3.DEBUG = true; - -function vec3(x, y, z) { - if (!(this instanceof vec3)) { - // if vec3 is called as a function then re-invoke as a constructor - // (so that `value instanceof vec3` holds true for created values) - return new vec3(x, y, z); - } - - // unfold default arguments (vec3(), vec3(.5), vec3(0,1), etc.) - this.x = x !== undefined ? x : 0; - this.y = y !== undefined ? y : this.x; - this.z = z !== undefined ? z : this.y; - - if (vec3.DEBUG && !this.isValid()) - throw new Error('vec3() -- invalid initial values ['+[].slice.call(arguments)+']'); -}; - diff --git a/scripts/simplifiedUI/system/assets/animations/Cheering.fbx b/scripts/simplifiedUI/system/assets/animations/Cheering.fbx deleted file mode 100644 index 8787bf4bd8..0000000000 Binary files a/scripts/simplifiedUI/system/assets/animations/Cheering.fbx and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/animations/Clapping.fbx b/scripts/simplifiedUI/system/assets/animations/Clapping.fbx deleted file mode 100644 index d05b41866d..0000000000 Binary files a/scripts/simplifiedUI/system/assets/animations/Clapping.fbx and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/animations/Crying.fbx b/scripts/simplifiedUI/system/assets/animations/Crying.fbx deleted file mode 100644 index 2e60ba2450..0000000000 Binary files a/scripts/simplifiedUI/system/assets/animations/Crying.fbx and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/animations/Dancing.fbx b/scripts/simplifiedUI/system/assets/animations/Dancing.fbx deleted file mode 100644 index 7759d273b7..0000000000 Binary files a/scripts/simplifiedUI/system/assets/animations/Dancing.fbx and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/animations/Fall.fbx b/scripts/simplifiedUI/system/assets/animations/Fall.fbx deleted file mode 100644 index 627e909bb4..0000000000 Binary files a/scripts/simplifiedUI/system/assets/animations/Fall.fbx and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/animations/Love.fbx b/scripts/simplifiedUI/system/assets/animations/Love.fbx deleted file mode 100644 index 159ccafd04..0000000000 Binary files a/scripts/simplifiedUI/system/assets/animations/Love.fbx and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/animations/Pointing.fbx b/scripts/simplifiedUI/system/assets/animations/Pointing.fbx deleted file mode 100644 index da3c9bbeca..0000000000 Binary files a/scripts/simplifiedUI/system/assets/animations/Pointing.fbx and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/animations/Sit1.fbx b/scripts/simplifiedUI/system/assets/animations/Sit1.fbx deleted file mode 100644 index db75219980..0000000000 Binary files a/scripts/simplifiedUI/system/assets/animations/Sit1.fbx and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/animations/Sit2.fbx b/scripts/simplifiedUI/system/assets/animations/Sit2.fbx deleted file mode 100644 index 400b599794..0000000000 Binary files a/scripts/simplifiedUI/system/assets/animations/Sit2.fbx and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/animations/Sit3.fbx b/scripts/simplifiedUI/system/assets/animations/Sit3.fbx deleted file mode 100644 index 174fd75c4e..0000000000 Binary files a/scripts/simplifiedUI/system/assets/animations/Sit3.fbx and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/animations/Surprised.fbx b/scripts/simplifiedUI/system/assets/animations/Surprised.fbx deleted file mode 100644 index 49362605b3..0000000000 Binary files a/scripts/simplifiedUI/system/assets/animations/Surprised.fbx and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/animations/Waving.fbx b/scripts/simplifiedUI/system/assets/animations/Waving.fbx deleted file mode 100644 index e2442f64f4..0000000000 Binary files a/scripts/simplifiedUI/system/assets/animations/Waving.fbx and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/data/createAppTooltips.json b/scripts/simplifiedUI/system/assets/data/createAppTooltips.json deleted file mode 100644 index b59797fca7..0000000000 --- a/scripts/simplifiedUI/system/assets/data/createAppTooltips.json +++ /dev/null @@ -1,623 +0,0 @@ -{ - "shape": { - "tooltip": "The shape of this entity's geometry." - }, - "color": { - "tooltip": "The RGB value of this entity." - }, - "text": { - "tooltip": "The text to display on the entity." - }, - "textColor": { - "tooltip": "The color of the text." - }, - "textAlpha": { - "tooltip": "The alpha of the text." - }, - "backgroundColor": { - "tooltip": "The color of the background." - }, - "backgroundAlpha": { - "tooltip": "The alpha of the background." - }, - "lineHeight": { - "tooltip": "The height of each line of text. This determines the size of the text." - }, - "textBillboardMode": { - "tooltip": "If enabled, determines how the entity will face the camera.", - "jsPropertyName": "billboardMode" - }, - "topMargin": { - "tooltip": "The top margin, in meters." - }, - "rightMargin": { - "tooltip": "The right margin, in meters." - }, - "bottomMargin": { - "tooltip": "The bottom margin, in meters." - }, - "leftMargin": { - "tooltip": "The left margin, in meters." - }, - "zoneShapeType": { - "tooltip": "The shape of the volume in which the zone's lighting effects and avatar permissions have effect.", - "jsPropertyName": "shapeType" - }, - "zoneCompoundShapeURL": { - "tooltip": "The model file to use for the compound shape if Shape Type is \"Use Compound Shape URL\".", - "jsPropertyName": "compoundShapeURL" - }, - "flyingAllowed": { - "tooltip": "If enabled, users can fly in the zone." - }, - "ghostingAllowed": { - "tooltip": "If enabled, users with avatar collisions turned off will not collide with content in the zone." - }, - "filterURL": { - "tooltip": "The URL of a JS file that checks for changes to entity properties within the zone. Runs periodically." - }, - "keyLightMode": { - "tooltip": "Configures the key light in the zone. This light is directional." - }, - "keyLight.color": { - "tooltip": "The color of the key light." - }, - "keyLight.intensity": { - "tooltip": "The intensity of the key light." - }, - "keyLight.direction.y": { - "tooltip": "The angle in deg at which light emits. Starts in the entity's -z direction, and rotates around its y axis." - }, - "keyLight.direction.x": { - "tooltip": "The angle in deg at which light emits. Starts in the entity's -z direction, and rotates around its x axis." - }, - "keyLight.castShadows": { - "tooltip": "If enabled, shadows are cast. The entity or avatar casting the shadow must also have Cast Shadows enabled." - }, - "skyboxMode": { - "tooltip": "Configures the skybox in the zone. The skybox is a cube map image." - }, - "skybox.color": { - "tooltip": "If the URL is blank, this changes the color of the sky, otherwise it modifies the color of the skybox." - }, - "skybox.url": { - "tooltip": "A cube map image that is used to render the sky." - }, - "ambientLightMode": { - "tooltip": "Configures the ambient light in the zone. Use this if you want your skybox to reflect light on the content." - }, - "ambientLight.ambientIntensity": { - "tooltip": "The intensity of the ambient light." - }, - "ambientLight.ambientURL": { - "tooltip": "A cube map image that defines the color of the light coming from each direction." - }, - "hazeMode": { - "tooltip": "Configures the haze in the scene." - }, - "haze.hazeRange": { - "tooltip": "How far the haze extends out. This is measured in meters." - }, - "haze.hazeAltitudeEffect": { - "tooltip": "If enabled, this adjusts the haze intensity as it gets higher." - }, - "haze.hazeBaseRef": { - "tooltip": "The base of the altitude range. Measured in entity space." - }, - "haze.hazeCeiling": { - "tooltip": "The ceiling of the altitude range. Measured in entity space." - }, - "haze.hazeColor": { - "tooltip": "The color of the haze." - }, - "haze.hazeBackgroundBlend": { - "tooltip": "How much the skybox shows through the haze. The higher the value, the more it shows through." - }, - "haze.hazeEnableGlare": { - "tooltip": "If enabled, a glare is enabled on the skybox, based on the key light." - }, - "haze.hazeGlareColor": { - "tooltip": "The color of the glare based on the key light." - }, - "haze.hazeGlareAngle": { - "tooltip": "The angular size of the glare and how much it encompasses the skybox, based on the key light." - }, - "bloomMode": { - "tooltip": "Configures how much bright areas of the scene glow." - }, - "bloom.bloomIntensity": { - "tooltip": "The intensity, or brightness, of the bloom effect." - }, - "bloom.bloomThreshold": { - "tooltip": "The cutoff of the bloom. The higher the value, the more only bright areas of the scene will glow." - }, - "bloom.bloomSize": { - "tooltip": "The radius of bloom. The higher the value, the larger the bloom." - }, - "avatarPriority": { - "tooltip": "Alter Avatars' update priorities." - }, - "modelURL": { - "tooltip": "A mesh model from an FBX or OBJ file." - }, - "shapeType": { - "tooltip": "The shape of the collision hull used if collisions are enabled. This affects how an entity collides." - }, - "compoundShapeURL": { - "tooltip": "The model file to use for the compound shape if Collision Shape is \"Compound\"." - }, - "animation.url": { - "tooltip": "An animation to play on the model." - }, - "animation.running": { - "tooltip": "If enabled, the animation on the model will play automatically." - }, - "animation.allowTranslation": { - "tooltip": "If enabled, this allows an entity to move in space during an animation." - }, - "animation.loop": { - "tooltip": "If enabled, then the animation will continuously repeat." - }, - "animation.hold": { - "tooltip": "If enabled, then rotations and translations of the last frame played are maintained when the animation stops." - }, - "animation.currentFrame": { - "tooltip": "The current frame being played in the animation." - }, - "animation.firstFrame": { - "tooltip": "The first frame to play in the animation." - }, - "animation.lastFrame": { - "tooltip": "The last frame to play in the animation." - }, - "animation.fps": { - "tooltip": "The speed of the animation." - }, - "textures": { - "tooltip": "A JSON string containing a texture. Use a name from the Original Texture property to override it." - }, - "originalTextures": { - "tooltip": "A JSON string containing the original texture used on the model." - }, - "imageURL": { - "tooltip": "The URL for the image source." - }, - "imageColor": { - "tooltip": "The tint to be applied to the image.", - "jsPropertyName": "color" - }, - "emissive": { - "tooltip": "If enabled, the image will display at full brightness." - }, - "subImage": { - "tooltip": "The area of the image that is displayed." - }, - "imageBillboardMode": { - "tooltip": "If enabled, determines how the entity will face the camera.", - "jsPropertyName": "billboardMode" - }, - "keepAspectRatio": { - "tooltip": "If enabled, the image will maintain its original aspect ratio." - }, - "sourceUrl": { - "tooltip": "The URL for the web page source." - }, - "dpi": { - "tooltip": "The resolution to display the page at, in pixels per inch. Use this to resize your web source in the frame." - }, - "isEmitting": { - "tooltip": "If enabled, then particles are emitted." - }, - "lifespan": { - "tooltip": "How long each particle lives, measured in seconds." - }, - "maxParticles": { - "tooltip": "The maximum number of particles to render at one time. Older particles are swapped out for new ones." - }, - "particleTextures": { - "tooltip": "The URL of a JPG or PNG image file to display for each particle.", - "jsPropertyName": "textures" - }, - "emitRate": { - "tooltip": "The number of particles per second to emit." - }, - "emitSpeed": { - "tooltip": "The speed that each particle is emitted at, measured in m/s." - }, - "speedSpread": { - "tooltip": "The spread in speeds at which particles are emitted at, resulting in a variety of speeds." - }, - "particleShapeType": { - "tooltip": "The shape of the surface from which to emit particles.", - "jsPropertyName": "shapeType" - }, - "particleCompoundShapeURL": { - "tooltip": "The model file to use for the particle emitter if Shape Type is \"Use Compound Shape URL\".", - "jsPropertyName": "compoundShapeURL" - }, - "emitDimensions": { - "tooltip": "The outer limit radius in dimensions that the particles can be emitted from." - }, - "emitOrientation": { - "tooltip": "The orientation of particle emission relative to the entity's axes." - }, - "emitRadiusStart": { - "tooltip": "The inner limit radius in dimensions that the particles start emitting from." - }, - "emitterShouldTrail": { - "tooltip": "If enabled, then particles are \"left behind\" as the emitter moves, otherwise they are not." - }, - "particleRadiusTriple": { - "tooltip": "The size of each particle.", - "jsPropertyName": "particleRadius" - }, - "particleRadius": { - "tooltip": "The size of each particle." - }, - "radiusStart": { - "tooltip": "The start size of each particle." - }, - "radiusFinish": { - "tooltip": "The finish size of each particle." - }, - "radiusSpread": { - "tooltip": "The spread in size that each particle is given, resulting in a variety of sizes." - }, - "particleColorTriple": { - "tooltip": "The color of each particle.", - "jsPropertyName": "color" - }, - "particleColor": { - "tooltip": "The color of each particle.", - "jsPropertyName": "color" - }, - "colorStart": { - "tooltip": "The start color of each particle." - }, - "colorFinish": { - "tooltip": "The finish color of each particle." - }, - "colorSpread": { - "tooltip": "The spread in color that each particle is given, resulting in a variety of colors." - }, - "particleAlphaTriple": { - "tooltip": "The alpha of each particle.", - "jsPropertyName": "alpha" - }, - "alpha": { - "tooltip": "The alpha of each particle." - }, - "alphaStart": { - "tooltip": "The start alpha of each particle." - }, - "alphaFinish": { - "tooltip": "The finish alpha of each particle." - }, - "alphaSpread": { - "tooltip": "The spread in alpha that each particle is given, resulting in a variety of alphas." - }, - "emitAcceleration": { - "tooltip": "The acceleration that is applied to each particle during its lifetime." - }, - "accelerationSpread": { - "tooltip": "The spread in accelerations that each particle is given, resulting in a variety of accelerations." - }, - "particleSpinTriple": { - "tooltip": "The spin of each particle.", - "jsPropertyName": "particleSpin" - }, - "particleSpin": { - "tooltip": "The spin of each particle." - }, - "spinStart": { - "tooltip": "The start spin of each particle." - }, - "spinFinish": { - "tooltip": "The finish spin of each particle." - }, - "spinSpread": { - "tooltip": "The spread in spin that each particle is given, resulting in a variety of spins." - }, - "rotateWithEntity": { - "tooltip": "If enabled, each particle will spin relative to the rotation of the entity as a whole." - }, - "particlePolarTriple": { - "tooltip": "The angle range in deg at which particles are emitted. Starts in the entity's -z direction, and rotates around its y axis.", - "skipJSProperty": true - }, - "polarStart": { - "tooltip": "The start angle in deg at which particles are emitted. Starts in the entity's -z direction, and rotates around its y axis." - }, - "polarFinish": { - "tooltip": "The finish angle in deg at which particles are emitted. Starts in the entity's -z direction, and rotates around its y axis." - }, - "particleAzimuthTriple": { - "tooltip": "The angle range in deg at which particles are emitted. Starts in the entity's -x direction, and rotates around its z axis.", - "skipJSProperty": true - }, - "azimuthStart": { - "tooltip": "The start angle in deg at which particles are emitted. Starts in the entity's -x direction, and rotates around its z axis." - }, - "azimuthFinish": { - "tooltip": "The finish angle in deg at which particles are emitted. Starts in the entity's -x direction, and rotates around its z axis." - }, - "lightColor": { - "tooltip": "The color of the light emitted.", - "jsPropertyName": "color" - }, - "intensity": { - "tooltip": "The brightness of the light." - }, - "falloffRadius": { - "tooltip": "The distance from the light's center where the intensity is reduced." - }, - "isSpotlight": { - "tooltip": "If enabled, then the light is directional, otherwise the light is a point light which emits light in all directions." - }, - "exponent": { - "tooltip": "Affects the softness of the spotlight beam; the higher the value, the softer the beam." - }, - "cutoff": { - "tooltip": "Affects the size of the spotlight beam; the higher the value, the larger the beam." - }, - "materialURL": { - "tooltip": "The URL to an external JSON file or \"materialData\", \"materialData? to use Material Data." - }, - "materialData": { - "tooltip": "Can be used instead of a JSON file when material set to materialData." - }, - "parentMaterialName": { - "tooltip": "The target mesh indices or material names that this material entity should be assigned to on it's parent. This only supports parents that are Avatars as well as Shape or Model entity types." - }, - "priority": { - "tooltip": "The priority of the material, where a larger number means higher priority. Original materials = 0." - }, - "materialMappingMode": { - "tooltip": "How the material is mapped to the entity. If set to \"UV space\", then the material will be applied with the target entity's UV coordinates. If set to \"3D Projected\", then the 3D transform of the material entity will be used." - }, - "materialMappingPos": { - "tooltip": "The offset position of the bottom left of the material within the parent's UV space." - }, - "materialMappingScale": { - "tooltip": "How many times the material will repeat in each direction within the parent's UV space." - }, - "materialMappingRot": { - "tooltip": "How much to rotate the material within the parent's UV-space, in degrees." - }, - "materialRepeat": { - "tooltip": "If enabled, the material will repeat, otherwise it will clamp." - }, - "followCamera": { - "tooltip": "If enabled, the grid is always visible even as the camera moves to another position." - }, - "majorGridEvery": { - "tooltip": "The number of \"Minor Grid Every\" intervals at which to draw a thick grid line." - }, - "minorGridEvery": { - "tooltip": "The real number of meters at which to draw thin grid lines." - }, - "id": { - "tooltip": "The unique identifier of this entity." - }, - "name": { - "tooltip": "The name of this entity." - }, - "description": { - "tooltip": "Use this field to describe the entity." - }, - "position": { - "tooltip": "The global position of this entity." - }, - "localPosition": { - "tooltip": "The local position of this entity." - }, - "rotation": { - "tooltip": "The global rotation of this entity." - }, - "localRotation": { - "tooltip": "The local rotation of this entity." - }, - "dimensions": { - "tooltip": "The global dimensions of this entity." - }, - "localDimensions": { - "tooltip": "The local dimensions of this entity." - }, - "scale": { - "tooltip": "The global scaling of this entity.", - "skipJSProperty": true - }, - "registrationPoint": { - "tooltip": "The point in the entity at which the entity is rotated about." - }, - "visible": { - "tooltip": "If enabled, this entity will be visible." - }, - "locked": { - "tooltip": "If enabled, this entity will be locked." - }, - "collisionless": { - "tooltip": "If enabled, this entity will collide with other entities or avatars." - }, - "dynamic": { - "tooltip": "If enabled, this entity has collisions associated with it that can affect its movement." - }, - "collidesWithStatic": { - "tooltip": "If enabled, this entity will collide with other non-moving, static entities.", - "jsPropertyName": "collidesWith" - }, - "collidesWithDynamic": { - "tooltip": "If enabled, this entity will collide with other dynamic entities.", - "jsPropertyName": "collidesWith" - }, - "collidesWithKinematic": { - "tooltip": "If enabled, this entity will collide with other kinematic entities (they have velocity but are not dynamic).", - "jsPropertyName": "collidesWith" - }, - "collidesWithOtherAvatar": { - "tooltip": "If enabled, this entity will collide with other user's avatars.", - "jsPropertyName": "collidesWith" - }, - "collidesWithMyAvatar": { - "tooltip": "If enabled, this entity will collide with your own avatar.", - "jsPropertyName": "collidesWith" - }, - "collisionSoundURL": { - "tooltip": "The URL of a sound to play when the entity collides with something else." - }, - "grab.grabbable": { - "tooltip": "If enabled, this entity will allow grabbing input and will be movable." - }, - "grab.triggerable": { - "tooltip": "If enabled, the collider on this entity is used for triggering events." - }, - "cloneable": { - "tooltip": "If enabled, this entity can be duplicated." - }, - "cloneLifetime": { - "tooltip": "The lifetime for clones of this entity." - }, - "cloneLimit": { - "tooltip": "The total number of clones of this entity that can exist in the domain at any given time." - }, - "cloneDynamic": { - "tooltip": "If enabled, then clones created from this entity will be dynamic, allowing the clone to collide." - }, - "cloneAvatarEntity": { - "tooltip": "If enabled, then clones created from this entity will be created as avatar entities." - }, - "grab.grabFollowsController": { - "tooltip": "If enabled, grabbed entities will follow the movements of your hand controller instead of your avatar's hand." - }, - "canCastShadow": { - "tooltip": "If enabled, this geometry of this entity casts shadows when a shadow-casting light source shines on it." - }, - "ignorePickIntersection": { - "tooltip": "If enabled, this entity will not be considered for ray picks, and will also not occlude other entities when picking." - }, - "parentID": { - "tooltip": "The ID of the entity or avatar that this entity is parented to." - }, - "parentJointIndex": { - "tooltip": "If the entity is parented to an avatar, this joint defines where on the avatar the entity is parented." - }, - "href": { - "tooltip": "The URL that will be opened when a user clicks on this entity. Useful for web pages and portals." - }, - "script": { - "tooltip": "The URL to an external JS file to add behaviors to the client." - }, - "serverScripts": { - "tooltip": "The URL to an external JS file to add behaviors to the server." - }, - "serverScriptsStatus": { - "tooltip": "The status of the server script, if provided. This shows if it's running or has an error.", - "skipJSProperty": true - }, - "hasLifetime": { - "tooltip": "If enabled, the entity will disappear after a certain amount of time specified by Lifetime.", - "jsPropertyName": "lifetime" - }, - "lifetime": { - "tooltip": "The time this entity will exist in the environment for." - }, - "userData": { - "tooltip": "Used to store extra data about the entity in JSON format." - }, - "localVelocity": { - "tooltip": "The linear velocity vector of the entity. The velocity at which this entity moves forward in space." - }, - "damping": { - "tooltip": "The linear damping to slow down the linear velocity of an entity over time." - }, - "localAngularVelocity": { - "tooltip": "The angular velocity of the entity in rad/s with respect to its axes, about its pivot point." - }, - "angularDamping": { - "tooltip": "The angular damping to slow down the angular velocity of an entity over time." - }, - "restitution": { - "tooltip": "If enabled, the entity can bounce against other objects that also have Bounciness." - }, - "friction": { - "tooltip": "The friction applied to slow down an entity when it's moving against another entity." - }, - "density": { - "tooltip": "The density of the entity. The higher the density, the harder the entity is to move." - }, - "gravity": { - "tooltip": "The acceleration due to gravity that the entity should move with, in world space." - }, - "acceleration": { - "tooltip": "A acceleration that the entity should move with, in world space." - }, - "renderLayer": { - "tooltip": "The layer on which this entity is rendered." - }, - "primitiveMode": { - "tooltip": "The mode in which to draw an entity, either \"Solid\" or \"Wireframe\"." - }, - "groupCulled": { - "tooltip": "If false, individual pieces of the entity may be culled by the render engine. If true, either the entire entity will be culled, or it won't at all." - }, - "webColor": { - "tooltip": "The tint of the web entity." - }, - "webAlpha": { - "tooltip": "The alpha of the web entity." - }, - "maxFPS": { - "tooltip": "The FPS at which to render the web entity. Higher values will have a performance impact." - }, - "scriptURL": { - "tooltip": "The URL of a script to inject into the web page." - }, - "alignToGrid": { - "tooltip": "Used to align entities to the grid, or floor of the environment.", - "skipJSProperty": true - }, - "createModel": { - "tooltip": "An entity that is based on a custom mesh created from an .OBJ or .FBX.", - "skipJSProperty": true - }, - "createShape": { - "tooltip": "An entity that has many different primitive shapes.", - "skipJSProperty": true - }, - "createLight": { - "tooltip": "An entity that emits light.", - "skipJSProperty": true - }, - "createText": { - "tooltip": "An entity that displays text on a panel.", - "skipJSProperty": true - }, - "createImage": { - "tooltip": "An entity that displays an image on a panel.", - "skipJSProperty": true - }, - "createWeb": { - "tooltip": "An entity that displays a web page on a panel.", - "skipJSProperty": true - }, - "createZone": { - "tooltip": "An entity that can be used for skyboxes, lighting, and can constrain or change avatar behaviors.", - "skipJSProperty": true - }, - "createParticle": { - "tooltip": "An entity that emits particles.", - "skipJSProperty": true - }, - "createMaterial": { - "tooltip": "An entity that creates a material that can be attached to a Shape or Model.", - "skipJSProperty": true - }, - "useAssetServer": { - "tooltip": "A server that hosts content and assets. You can't take items that are hosted here into other domains.", - "skipJSProperty": true - }, - "importNewEntity": { - "tooltip": "Import a local or hosted file that can be used across domains.", - "skipJSProperty": true - } -} diff --git a/scripts/simplifiedUI/system/assets/images/Overlay-Viz-blank.png b/scripts/simplifiedUI/system/assets/images/Overlay-Viz-blank.png deleted file mode 100644 index bbbf44f7a9..0000000000 Binary files a/scripts/simplifiedUI/system/assets/images/Overlay-Viz-blank.png and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/images/Particle-Sprite-Smoke-1.png b/scripts/simplifiedUI/system/assets/images/Particle-Sprite-Smoke-1.png deleted file mode 100644 index 78c9b3da4a..0000000000 Binary files a/scripts/simplifiedUI/system/assets/images/Particle-Sprite-Smoke-1.png and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/images/close-small-light.svg b/scripts/simplifiedUI/system/assets/images/close-small-light.svg deleted file mode 100644 index f9edf95fca..0000000000 --- a/scripts/simplifiedUI/system/assets/images/close-small-light.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/grabsprite-3.png b/scripts/simplifiedUI/system/assets/images/grabsprite-3.png deleted file mode 100644 index 4ecc772a41..0000000000 Binary files a/scripts/simplifiedUI/system/assets/images/grabsprite-3.png and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/images/ignore-target.svg b/scripts/simplifiedUI/system/assets/images/ignore-target.svg deleted file mode 100644 index 3d685139ec..0000000000 --- a/scripts/simplifiedUI/system/assets/images/ignore-target.svg +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/kick-target.svg b/scripts/simplifiedUI/system/assets/images/kick-target.svg deleted file mode 100644 index 21cb3a5462..0000000000 --- a/scripts/simplifiedUI/system/assets/images/kick-target.svg +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/lock.svg b/scripts/simplifiedUI/system/assets/images/lock.svg deleted file mode 100644 index bb9658de00..0000000000 --- a/scripts/simplifiedUI/system/assets/images/lock.svg +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/lod-a.svg b/scripts/simplifiedUI/system/assets/images/lod-a.svg deleted file mode 100644 index 6845e0ff78..0000000000 --- a/scripts/simplifiedUI/system/assets/images/lod-a.svg +++ /dev/null @@ -1,46 +0,0 @@ - - - -image/svg+xml \ No newline at end of file diff --git a/scripts/simplifiedUI/system/assets/images/lod-i.svg b/scripts/simplifiedUI/system/assets/images/lod-i.svg deleted file mode 100644 index f909f3b495..0000000000 --- a/scripts/simplifiedUI/system/assets/images/lod-i.svg +++ /dev/null @@ -1,46 +0,0 @@ - - - -image/svg+xml \ No newline at end of file diff --git a/scripts/simplifiedUI/system/assets/images/luci-a.svg b/scripts/simplifiedUI/system/assets/images/luci-a.svg deleted file mode 100644 index 40e1481eba..0000000000 --- a/scripts/simplifiedUI/system/assets/images/luci-a.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/luci-i.svg b/scripts/simplifiedUI/system/assets/images/luci-i.svg deleted file mode 100644 index 2d73339908..0000000000 --- a/scripts/simplifiedUI/system/assets/images/luci-i.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/materials/GridPattern.json b/scripts/simplifiedUI/system/assets/images/materials/GridPattern.json deleted file mode 100644 index 468b709ea4..0000000000 --- a/scripts/simplifiedUI/system/assets/images/materials/GridPattern.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "materialVersion": 1, - "materials": { - "albedo": [ - 0.0, - 0.0, - 7.0 - ], - "unlit": true, - "opacity": 0.4, - "albedoMap": "GridPattern.png" - } -} diff --git a/scripts/simplifiedUI/system/assets/images/materials/GridPattern.png b/scripts/simplifiedUI/system/assets/images/materials/GridPattern.png deleted file mode 100644 index 2ecc7f8570..0000000000 Binary files a/scripts/simplifiedUI/system/assets/images/materials/GridPattern.png and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/images/min-max-toggle.svg b/scripts/simplifiedUI/system/assets/images/min-max-toggle.svg deleted file mode 100644 index 1699cc705d..0000000000 --- a/scripts/simplifiedUI/system/assets/images/min-max-toggle.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/mute-target.svg b/scripts/simplifiedUI/system/assets/images/mute-target.svg deleted file mode 100644 index 1ed642c79e..0000000000 --- a/scripts/simplifiedUI/system/assets/images/mute-target.svg +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/progress-bar-2k.svg b/scripts/simplifiedUI/system/assets/images/progress-bar-2k.svg deleted file mode 100644 index 45758c7c68..0000000000 --- a/scripts/simplifiedUI/system/assets/images/progress-bar-2k.svg +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/progress-bar-4k.svg b/scripts/simplifiedUI/system/assets/images/progress-bar-4k.svg deleted file mode 100644 index 609ab9610b..0000000000 --- a/scripts/simplifiedUI/system/assets/images/progress-bar-4k.svg +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/progress-bar-text.svg b/scripts/simplifiedUI/system/assets/images/progress-bar-text.svg deleted file mode 100644 index 05ebb3f637..0000000000 --- a/scripts/simplifiedUI/system/assets/images/progress-bar-text.svg +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/run.svg b/scripts/simplifiedUI/system/assets/images/run.svg deleted file mode 100644 index 0957166346..0000000000 --- a/scripts/simplifiedUI/system/assets/images/run.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/scripts/simplifiedUI/system/assets/images/textures/dirt.jpeg b/scripts/simplifiedUI/system/assets/images/textures/dirt.jpeg deleted file mode 100644 index 694e4f3c9a..0000000000 Binary files a/scripts/simplifiedUI/system/assets/images/textures/dirt.jpeg and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/images/textures/grass.png b/scripts/simplifiedUI/system/assets/images/textures/grass.png deleted file mode 100644 index d51fe0cf28..0000000000 Binary files a/scripts/simplifiedUI/system/assets/images/textures/grass.png and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/images/tools/add-remove-friends.svg b/scripts/simplifiedUI/system/assets/images/tools/add-remove-friends.svg deleted file mode 100644 index 6ee9ce842d..0000000000 --- a/scripts/simplifiedUI/system/assets/images/tools/add-remove-friends.svg +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/tools/assets-01.svg b/scripts/simplifiedUI/system/assets/images/tools/assets-01.svg deleted file mode 100644 index d7bdd1d7f0..0000000000 --- a/scripts/simplifiedUI/system/assets/images/tools/assets-01.svg +++ /dev/null @@ -1,186 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/tools/bubble.svg b/scripts/simplifiedUI/system/assets/images/tools/bubble.svg deleted file mode 100644 index 064b7734a9..0000000000 --- a/scripts/simplifiedUI/system/assets/images/tools/bubble.svg +++ /dev/null @@ -1,275 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/tools/cube-01.svg b/scripts/simplifiedUI/system/assets/images/tools/cube-01.svg deleted file mode 100644 index f8cf96e4f2..0000000000 --- a/scripts/simplifiedUI/system/assets/images/tools/cube-01.svg +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/tools/directory.svg b/scripts/simplifiedUI/system/assets/images/tools/directory.svg deleted file mode 100644 index 09f3c14bf0..0000000000 --- a/scripts/simplifiedUI/system/assets/images/tools/directory.svg +++ /dev/null @@ -1,255 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/tools/edit.svg b/scripts/simplifiedUI/system/assets/images/tools/edit.svg deleted file mode 100644 index f65e0cd84d..0000000000 --- a/scripts/simplifiedUI/system/assets/images/tools/edit.svg +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/tools/help.svg b/scripts/simplifiedUI/system/assets/images/tools/help.svg deleted file mode 100644 index b7fa8ca5cd..0000000000 --- a/scripts/simplifiedUI/system/assets/images/tools/help.svg +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/tools/ignore.svg b/scripts/simplifiedUI/system/assets/images/tools/ignore.svg deleted file mode 100644 index f315c5f249..0000000000 --- a/scripts/simplifiedUI/system/assets/images/tools/ignore.svg +++ /dev/null @@ -1,177 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/tools/kick.svg b/scripts/simplifiedUI/system/assets/images/tools/kick.svg deleted file mode 100644 index 1eed6e7f43..0000000000 --- a/scripts/simplifiedUI/system/assets/images/tools/kick.svg +++ /dev/null @@ -1,140 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/tools/light-01.svg b/scripts/simplifiedUI/system/assets/images/tools/light-01.svg deleted file mode 100644 index 4573c7d636..0000000000 --- a/scripts/simplifiedUI/system/assets/images/tools/light-01.svg +++ /dev/null @@ -1,112 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/tools/market.svg b/scripts/simplifiedUI/system/assets/images/tools/market.svg deleted file mode 100644 index 0cec030933..0000000000 --- a/scripts/simplifiedUI/system/assets/images/tools/market.svg +++ /dev/null @@ -1,147 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/tools/mic.svg b/scripts/simplifiedUI/system/assets/images/tools/mic.svg deleted file mode 100644 index 3a7c183bc4..0000000000 --- a/scripts/simplifiedUI/system/assets/images/tools/mic.svg +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/tools/min-max-toggle.svg b/scripts/simplifiedUI/system/assets/images/tools/min-max-toggle.svg deleted file mode 100644 index 1699cc705d..0000000000 --- a/scripts/simplifiedUI/system/assets/images/tools/min-max-toggle.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/tools/model-01.svg b/scripts/simplifiedUI/system/assets/images/tools/model-01.svg deleted file mode 100644 index e760d74d5c..0000000000 --- a/scripts/simplifiedUI/system/assets/images/tools/model-01.svg +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/tools/particle-01.svg b/scripts/simplifiedUI/system/assets/images/tools/particle-01.svg deleted file mode 100644 index cfcfb0ea7f..0000000000 --- a/scripts/simplifiedUI/system/assets/images/tools/particle-01.svg +++ /dev/null @@ -1,161 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/tools/people.svg b/scripts/simplifiedUI/system/assets/images/tools/people.svg deleted file mode 100644 index 5fedfefa75..0000000000 --- a/scripts/simplifiedUI/system/assets/images/tools/people.svg +++ /dev/null @@ -1,161 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/tools/polyvox.svg b/scripts/simplifiedUI/system/assets/images/tools/polyvox.svg deleted file mode 100644 index 69f1e978ff..0000000000 --- a/scripts/simplifiedUI/system/assets/images/tools/polyvox.svg +++ /dev/null @@ -1,39 +0,0 @@ - - - - -polyvox - - - -voxels - - diff --git a/scripts/simplifiedUI/system/assets/images/tools/snap.svg b/scripts/simplifiedUI/system/assets/images/tools/snap.svg deleted file mode 100644 index c540f307ae..0000000000 --- a/scripts/simplifiedUI/system/assets/images/tools/snap.svg +++ /dev/null @@ -1,109 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/tools/sphere-01.svg b/scripts/simplifiedUI/system/assets/images/tools/sphere-01.svg deleted file mode 100644 index 975199c8da..0000000000 --- a/scripts/simplifiedUI/system/assets/images/tools/sphere-01.svg +++ /dev/null @@ -1,108 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/tools/sphere-add.svg b/scripts/simplifiedUI/system/assets/images/tools/sphere-add.svg deleted file mode 100644 index 59ca489b5f..0000000000 --- a/scripts/simplifiedUI/system/assets/images/tools/sphere-add.svg +++ /dev/null @@ -1,77 +0,0 @@ - - - -image/svg+xmladd - \ No newline at end of file diff --git a/scripts/simplifiedUI/system/assets/images/tools/sphere-delete.svg b/scripts/simplifiedUI/system/assets/images/tools/sphere-delete.svg deleted file mode 100644 index 6997654500..0000000000 --- a/scripts/simplifiedUI/system/assets/images/tools/sphere-delete.svg +++ /dev/null @@ -1,76 +0,0 @@ - - - -image/svg+xmldelete - \ No newline at end of file diff --git a/scripts/simplifiedUI/system/assets/images/tools/steam-invite.svg b/scripts/simplifiedUI/system/assets/images/tools/steam-invite.svg deleted file mode 100644 index ce225cca68..0000000000 --- a/scripts/simplifiedUI/system/assets/images/tools/steam-invite.svg +++ /dev/null @@ -1,112 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/tools/switch.svg b/scripts/simplifiedUI/system/assets/images/tools/switch.svg deleted file mode 100644 index e67a9aac04..0000000000 --- a/scripts/simplifiedUI/system/assets/images/tools/switch.svg +++ /dev/null @@ -1,167 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/tools/text-01.svg b/scripts/simplifiedUI/system/assets/images/tools/text-01.svg deleted file mode 100644 index d33d66d4a5..0000000000 --- a/scripts/simplifiedUI/system/assets/images/tools/text-01.svg +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/tools/upload-01.svg b/scripts/simplifiedUI/system/assets/images/tools/upload-01.svg deleted file mode 100644 index 149b10f3bc..0000000000 --- a/scripts/simplifiedUI/system/assets/images/tools/upload-01.svg +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/tools/voxel-add.svg b/scripts/simplifiedUI/system/assets/images/tools/voxel-add.svg deleted file mode 100644 index 8e6e2c5b35..0000000000 --- a/scripts/simplifiedUI/system/assets/images/tools/voxel-add.svg +++ /dev/null @@ -1,104 +0,0 @@ - - - -image/svg+xmladd - \ No newline at end of file diff --git a/scripts/simplifiedUI/system/assets/images/tools/voxel-delete.svg b/scripts/simplifiedUI/system/assets/images/tools/voxel-delete.svg deleted file mode 100644 index 0b0d0b9787..0000000000 --- a/scripts/simplifiedUI/system/assets/images/tools/voxel-delete.svg +++ /dev/null @@ -1,103 +0,0 @@ - - - -image/svg+xmldelete - \ No newline at end of file diff --git a/scripts/simplifiedUI/system/assets/images/tools/voxel-terrain.svg b/scripts/simplifiedUI/system/assets/images/tools/voxel-terrain.svg deleted file mode 100644 index e5ed16dbcd..0000000000 --- a/scripts/simplifiedUI/system/assets/images/tools/voxel-terrain.svg +++ /dev/null @@ -1,101 +0,0 @@ - - - -image/svg+xmlterrain - \ No newline at end of file diff --git a/scripts/simplifiedUI/system/assets/images/tools/voxels.svg b/scripts/simplifiedUI/system/assets/images/tools/voxels.svg deleted file mode 100644 index a0dbd63d45..0000000000 --- a/scripts/simplifiedUI/system/assets/images/tools/voxels.svg +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/tools/web-01.svg b/scripts/simplifiedUI/system/assets/images/tools/web-01.svg deleted file mode 100644 index 903b3ac819..0000000000 --- a/scripts/simplifiedUI/system/assets/images/tools/web-01.svg +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/tools/zone-01.svg b/scripts/simplifiedUI/system/assets/images/tools/zone-01.svg deleted file mode 100644 index 29d17e5187..0000000000 --- a/scripts/simplifiedUI/system/assets/images/tools/zone-01.svg +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/unlock.svg b/scripts/simplifiedUI/system/assets/images/unlock.svg deleted file mode 100644 index 789a8b0ed5..0000000000 --- a/scripts/simplifiedUI/system/assets/images/unlock.svg +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/models/Avatar-Overlay-v1.fbx b/scripts/simplifiedUI/system/assets/models/Avatar-Overlay-v1.fbx deleted file mode 100644 index db710702f2..0000000000 Binary files a/scripts/simplifiedUI/system/assets/models/Avatar-Overlay-v1.fbx and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/models/Bubble-v14.fbx b/scripts/simplifiedUI/system/assets/models/Bubble-v14.fbx deleted file mode 100644 index c7d3122f00..0000000000 Binary files a/scripts/simplifiedUI/system/assets/models/Bubble-v14.fbx and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/models/black-sphere.fbx b/scripts/simplifiedUI/system/assets/models/black-sphere.fbx deleted file mode 100644 index 2e6dea233f..0000000000 Binary files a/scripts/simplifiedUI/system/assets/models/black-sphere.fbx and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/models/miniTabletBlank.fbx b/scripts/simplifiedUI/system/assets/models/miniTabletBlank.fbx deleted file mode 100644 index a2faa2a80a..0000000000 Binary files a/scripts/simplifiedUI/system/assets/models/miniTabletBlank.fbx and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/models/oculusSensorv11.fbx b/scripts/simplifiedUI/system/assets/models/oculusSensorv11.fbx deleted file mode 100644 index 52fadc77dc..0000000000 Binary files a/scripts/simplifiedUI/system/assets/models/oculusSensorv11.fbx and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/models/teleport-cancel.fbx b/scripts/simplifiedUI/system/assets/models/teleport-cancel.fbx deleted file mode 100644 index 1c12e28159..0000000000 Binary files a/scripts/simplifiedUI/system/assets/models/teleport-cancel.fbx and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/models/teleport-destination.fbm/Teleportation-Destination-Texture2.png b/scripts/simplifiedUI/system/assets/models/teleport-destination.fbm/Teleportation-Destination-Texture2.png deleted file mode 100644 index eb9addcfca..0000000000 Binary files a/scripts/simplifiedUI/system/assets/models/teleport-destination.fbm/Teleportation-Destination-Texture2.png and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/models/teleport-destination.fbx b/scripts/simplifiedUI/system/assets/models/teleport-destination.fbx deleted file mode 100644 index 5fdb0d56af..0000000000 Binary files a/scripts/simplifiedUI/system/assets/models/teleport-destination.fbx and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/models/teleport-seat.fbx b/scripts/simplifiedUI/system/assets/models/teleport-seat.fbx deleted file mode 100644 index cd7a9abc7e..0000000000 Binary files a/scripts/simplifiedUI/system/assets/models/teleport-seat.fbx and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/models/teleportationSpotBasev8.fbx b/scripts/simplifiedUI/system/assets/models/teleportationSpotBasev8.fbx deleted file mode 100644 index d651575dea..0000000000 Binary files a/scripts/simplifiedUI/system/assets/models/teleportationSpotBasev8.fbx and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/models/trackingSpacev18.fbx b/scripts/simplifiedUI/system/assets/models/trackingSpacev18.fbx deleted file mode 100644 index 16597eb285..0000000000 Binary files a/scripts/simplifiedUI/system/assets/models/trackingSpacev18.fbx and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/sounds/bubble.wav b/scripts/simplifiedUI/system/assets/sounds/bubble.wav deleted file mode 100644 index fd23a235d4..0000000000 Binary files a/scripts/simplifiedUI/system/assets/sounds/bubble.wav and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/sounds/button-click.wav b/scripts/simplifiedUI/system/assets/sounds/button-click.wav deleted file mode 100644 index 30a097ce45..0000000000 Binary files a/scripts/simplifiedUI/system/assets/sounds/button-click.wav and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/sounds/button-hover.wav b/scripts/simplifiedUI/system/assets/sounds/button-hover.wav deleted file mode 100644 index cd76d0174c..0000000000 Binary files a/scripts/simplifiedUI/system/assets/sounds/button-hover.wav and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/sounds/countdown-tick.wav b/scripts/simplifiedUI/system/assets/sounds/countdown-tick.wav deleted file mode 100644 index 015e1f642e..0000000000 Binary files a/scripts/simplifiedUI/system/assets/sounds/countdown-tick.wav and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/sounds/entitySnap.wav b/scripts/simplifiedUI/system/assets/sounds/entitySnap.wav deleted file mode 100644 index 4584f3dcaa..0000000000 Binary files a/scripts/simplifiedUI/system/assets/sounds/entitySnap.wav and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/sounds/finish-recording.wav b/scripts/simplifiedUI/system/assets/sounds/finish-recording.wav deleted file mode 100644 index f224049f97..0000000000 Binary files a/scripts/simplifiedUI/system/assets/sounds/finish-recording.wav and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/sounds/goodbye.wav b/scripts/simplifiedUI/system/assets/sounds/goodbye.wav deleted file mode 100644 index bd6c51a5c0..0000000000 Binary files a/scripts/simplifiedUI/system/assets/sounds/goodbye.wav and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/sounds/hello.wav b/scripts/simplifiedUI/system/assets/sounds/hello.wav deleted file mode 100644 index 6269dab5db..0000000000 Binary files a/scripts/simplifiedUI/system/assets/sounds/hello.wav and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/sounds/notification-general1.raw b/scripts/simplifiedUI/system/assets/sounds/notification-general1.raw deleted file mode 100644 index be81fa15c5..0000000000 Binary files a/scripts/simplifiedUI/system/assets/sounds/notification-general1.raw and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/sounds/notification-general2.raw b/scripts/simplifiedUI/system/assets/sounds/notification-general2.raw deleted file mode 100644 index 58f0bac19c..0000000000 Binary files a/scripts/simplifiedUI/system/assets/sounds/notification-general2.raw and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/sounds/rezzing.wav b/scripts/simplifiedUI/system/assets/sounds/rezzing.wav deleted file mode 100644 index 3c059aecdf..0000000000 Binary files a/scripts/simplifiedUI/system/assets/sounds/rezzing.wav and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/sounds/short1.wav b/scripts/simplifiedUI/system/assets/sounds/short1.wav deleted file mode 100644 index fb03f5dd49..0000000000 Binary files a/scripts/simplifiedUI/system/assets/sounds/short1.wav and /dev/null differ diff --git a/scripts/simplifiedUI/system/assets/sounds/start-recording.wav b/scripts/simplifiedUI/system/assets/sounds/start-recording.wav deleted file mode 100644 index 71c69f3372..0000000000 Binary files a/scripts/simplifiedUI/system/assets/sounds/start-recording.wav and /dev/null differ diff --git a/scripts/simplifiedUI/system/attachedEntitiesManager.js b/scripts/simplifiedUI/system/attachedEntitiesManager.js deleted file mode 100644 index 061e27f595..0000000000 --- a/scripts/simplifiedUI/system/attachedEntitiesManager.js +++ /dev/null @@ -1,285 +0,0 @@ -// -// attachedEntitiesManager.js -// -// Created by Seth Alves on 2016-1-20 -// Copyright 2016 High Fidelity, Inc. -// -// This script handles messages from the grab script related to wearables, and interacts with a doppelganger. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -Script.include("libraries/utils.js"); - -var DEFAULT_WEARABLE_DATA = { - joints: {} -}; - - -var MINIMUM_DROP_DISTANCE_FROM_JOINT = 0.8; -var ATTACHED_ENTITY_SEARCH_DISTANCE = 10.0; -var ATTACHED_ENTITIES_SETTINGS_KEY = "ATTACHED_ENTITIES"; -var DRESSING_ROOM_DISTANCE = 2.0; -var SHOW_TOOL_BAR = false; - -// tool bar - -if (SHOW_TOOL_BAR) { - var BUTTON_SIZE = 64; - var PADDING = 6; - Script.include(["libraries/toolBars.js"]); - - var toolBar = new ToolBar(0, 0, ToolBar.HORIZONTAL, "highfidelity.attachedEntities.toolbar"); - var lockButton = toolBar.addTool({ - width: BUTTON_SIZE, - height: BUTTON_SIZE, - imageURL: Script.resolvePath("assets/images/lock.svg"), - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1, - visible: true - }, false); -} - - -function mousePressEvent(event) { - var clickedOverlay = Overlays.getOverlayAtPoint({ - x: event.x, - y: event.y - }); - - if (lockButton === toolBar.clicked(clickedOverlay)) { - manager.toggleLocked(); - } -} - -function scriptEnding() { - if (SHOW_TOOL_BAR) { - toolBar.cleanup(); - } -} - -if (SHOW_TOOL_BAR) { - Controller.mousePressEvent.connect(mousePressEvent); -} -Script.scriptEnding.connect(scriptEnding); - - - -// attached entites - - -function AttachedEntitiesManager() { - var clothingLocked = false; - - this.subscribeToMessages = function() { - Messages.subscribe('Hifi-Object-Manipulation'); - Messages.messageReceived.connect(this.handleWearableMessages); - } - - this.handleWearableMessages = function(channel, message, sender) { - if (channel !== 'Hifi-Object-Manipulation') { - return; - } - - var parsedMessage = null; - - try { - parsedMessage = JSON.parse(message); - } catch (e) { - print('error parsing wearable message'); - return; - } - - if (parsedMessage.action === 'update' || - parsedMessage.action === 'loaded') { - // ignore - } else if (parsedMessage.action === 'release') { - manager.handleEntityRelease(parsedMessage.grabbedEntity, parsedMessage.joint) - // manager.saveAttachedEntities(); - } else if (parsedMessage.action === 'equip') { - // manager.saveAttachedEntities(); - } else { - print('attachedEntitiesManager -- unknown actions: ' + parsedMessage.action); - } - } - - this.handleEntityRelease = function(grabbedEntity, releasedFromJoint) { - // if this is still equipped, just rewrite the position information. - var grabData = getEntityCustomData('grabKey', grabbedEntity, {}); - - var allowedJoints = getEntityCustomData('wearable', grabbedEntity, DEFAULT_WEARABLE_DATA).joints; - - var props = Entities.getEntityProperties(grabbedEntity, ["position", "parentID", "parentJointIndex"]); - if (props.parentID === Uuid.NULL || props.parentID === MyAvatar.sessionUUID) { - var bestJointName = ""; - var bestJointIndex = -1; - var bestJointDistance = 0; - var bestJointOffset = null; - for (var jointName in allowedJoints) { - if ((releasedFromJoint == "LeftHand" || releasedFromJoint == "RightHand") && - (jointName == "LeftHand" || jointName == "RightHand")) { - // don't auto-attach to a hand if a hand just dropped something - continue; - } - var jointIndex = MyAvatar.getJointIndex(jointName); - if (jointIndex >= 0) { - var jointPosition = MyAvatar.getJointPosition(jointIndex); - var distanceFromJoint = Vec3.distance(jointPosition, props.position); - if (distanceFromJoint <= MINIMUM_DROP_DISTANCE_FROM_JOINT) { - if (bestJointIndex == -1 || distanceFromJoint < bestJointDistance) { - bestJointName = jointName; - bestJointIndex = jointIndex; - bestJointDistance = distanceFromJoint; - bestJointOffset = allowedJoints[jointName]; - } - } - } - } - - if (bestJointIndex != -1) { - var wearProps = Entities.getEntityProperties(grabbedEntity); - wearProps.parentID = MyAvatar.sessionUUID; - wearProps.parentJointIndex = bestJointIndex; - delete wearProps.localPosition; - delete wearProps.localRotation; - var updatePresets = false; - if (bestJointOffset && bestJointOffset.constructor === Array) { - if (!clothingLocked || bestJointOffset.length < 2) { - // we're unlocked or this thing didn't have a preset position, so update it - updatePresets = true; - } else { - // don't snap the entity to the preferred position if unlocked - wearProps.localPosition = bestJointOffset[0]; - wearProps.localRotation = bestJointOffset[1]; - } - } - - Entities.deleteEntity(grabbedEntity); - //the true boolean here after add entity adds it as an 'avatar entity', which can travel with you from server to server. - - var newEntity = Entities.addEntity(wearProps, true); - - if (updatePresets) { - this.updateRelativeOffsets(newEntity); - } - } else if (props.parentID != Uuid.NULL) { - // drop the entity and set it to have no parent (not on the avatar), unless it's being equipped in a hand. - if (props.parentID === MyAvatar.sessionUUID && - (props.parentJointIndex == MyAvatar.getJointIndex("RightHand") || - props.parentJointIndex == MyAvatar.getJointIndex("LeftHand"))) { - // this is equipped on a hand -- don't clear the parent. - } else { - var wearProps = Entities.getEntityProperties(grabbedEntity); - wearProps.parentID = Uuid.NULL; - wearProps.parentJointIndex = -1; - delete wearProps.id; - delete wearProps.created; - delete wearProps.age; - delete wearProps.ageAsText; - delete wearProps.naturalDimensions; - delete wearProps.naturalPosition; - delete wearProps.actionData; - delete wearProps.sittingPoints; - delete wearProps.boundingBox; - delete wearProps.avatarEntity; - delete wearProps.owningAvatarID; - delete wearProps.localPosition; - delete wearProps.localRotation; - Entities.deleteEntity(grabbedEntity); - Entities.addEntity(wearProps); - } - } - } - } - - this.updateRelativeOffsets = function(entityID) { - // save the preferred (current) relative position and rotation into the user-data of the entity - var props = Entities.getEntityProperties(entityID); - if (props.parentID == MyAvatar.sessionUUID) { - grabData = getEntityCustomData('grabKey', entityID, {}); - var wearableData = getEntityCustomData('wearable', entityID, DEFAULT_WEARABLE_DATA); - var currentJointName = MyAvatar.getJointNames()[props.parentJointIndex]; - wearableData.joints[currentJointName] = [props.localPosition, props.localRotation]; - setEntityCustomData('wearable', entityID, wearableData); - return true; - } - return false; - } - - // this.saveAttachedEntities = function() { - // print("--- saving attached entities ---"); - // saveData = []; - // var nearbyEntities = Entities.findEntities(MyAvatar.position, ATTACHED_ENTITY_SEARCH_DISTANCE); - // for (i = 0; i < nearbyEntities.length; i++) { - // var entityID = nearbyEntities[i]; - // if (this.updateRelativeOffsets(entityID)) { - // var props = Entities.getEntityProperties(entityID); // refresh, because updateRelativeOffsets changed them - // this.scrubProperties(props); - // saveData.push(props); - // } - // } - // Settings.setValue(ATTACHED_ENTITIES_SETTINGS_KEY, JSON.stringify(saveData)); - // } - - // this.scrubProperties = function(props) { - // var toScrub = ["queryAACube", "position", "rotation", - // "created", "ageAsText", "naturalDimensions", - // "naturalPosition", "velocity", "acceleration", - // "angularVelocity", "boundingBox"]; - // toScrub.forEach(function(propertyName) { - // delete props[propertyName]; - // }); - // // if the userData has a grabKey, clear old state - // if ("userData" in props) { - // try { - // parsedUserData = JSON.parse(props.userData); - // if ("grabKey" in parsedUserData) { - // parsedUserData.grabKey.refCount = 0; - // delete parsedUserData.grabKey["avatarId"]; - // props["userData"] = JSON.stringify(parsedUserData); - // } - // } catch (e) { - // } - // } - // } - - // this.loadAttachedEntities = function(grabbedEntity) { - // print("--- loading attached entities ---"); - // jsonAttachmentData = Settings.getValue(ATTACHED_ENTITIES_SETTINGS_KEY); - // var loadData = []; - // try { - // loadData = JSON.parse(jsonAttachmentData); - // } catch (e) { - // print('error parsing saved attachment data'); - // return; - // } - - // for (i = 0; i < loadData.length; i ++) { - // var savedProps = loadData[ i ]; - // var currentProps = Entities.getEntityProperties(savedProps.id); - // if (currentProps.id == savedProps.id && - // // TODO -- also check that parentJointIndex matches? - // currentProps.parentID == MyAvatar.sessionUUID) { - // // entity is already in-world. TODO -- patch it up? - // continue; - // } - // this.scrubProperties(savedProps); - // delete savedProps["id"]; - // savedProps.parentID = MyAvatar.sessionUUID; // this will change between sessions - // var loadedEntityID = Entities.addEntity(savedProps, true); - - // Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({ - // action: 'loaded', - // grabbedEntity: loadedEntityID - // })); - // } - // } -} - -var manager = new AttachedEntitiesManager(); -manager.subscribeToMessages(); \ No newline at end of file diff --git a/scripts/simplifiedUI/system/audio.js b/scripts/simplifiedUI/system/audio.js deleted file mode 100644 index a161b40ffd..0000000000 --- a/scripts/simplifiedUI/system/audio.js +++ /dev/null @@ -1,92 +0,0 @@ -"use strict"; - -// -// audio.js -// -// Created by Howard Stearns on 2 Jun 2016 -// Copyright 2016 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 -// -/* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ - -(function() { // BEGIN LOCAL_SCOPE - -var TABLET_BUTTON_NAME = "AUDIO"; -var HOME_BUTTON_TEXTURE = "http://hifi-content.s3.amazonaws.com/alan/dev/tablet-with-home-button.fbx/tablet-with-home-button.fbm/button-root.png"; -var AUDIO_QML_SOURCE = "hifi/audio/Audio.qml"; - -var MUTE_ICONS = { - icon: "icons/tablet-icons/mic-mute-i.svg", - activeIcon: "icons/tablet-icons/mic-mute-a.svg" -}; - -var UNMUTE_ICONS = { - icon: "icons/tablet-icons/mic-unmute-i.svg", - activeIcon: "icons/tablet-icons/mic-unmute-a.svg" -}; -var PTT_ICONS = { - icon: "icons/tablet-icons/mic-ptt-i.svg", - activeIcon: "icons/tablet-icons/mic-ptt-a.svg" -}; - -function onMuteToggled() { - if (Audio.pushToTalk) { - button.editProperties(PTT_ICONS); - } else if (Audio.muted) { - button.editProperties(MUTE_ICONS); - } else { - button.editProperties(UNMUTE_ICONS); - } -} - -var onAudioScreen = false; - -function onClicked() { - if (onAudioScreen) { - // for toolbar-mode: go back to home screen, this will close the window. - tablet.gotoHomeScreen(); - } else { - if (HMD.tabletID) { - Entities.editEntity(HMD.tabletID, { textures: JSON.stringify({ "tex.close": HOME_BUTTON_TEXTURE }) }); - } - tablet.loadQMLSource(AUDIO_QML_SOURCE); - } -} - -function onScreenChanged(type, url) { - onAudioScreen = (type === "QML" && url === AUDIO_QML_SOURCE); - // for toolbar mode: change button to active when window is first openend, false otherwise. - button.editProperties({isActive: onAudioScreen}); -} - -var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); -var button = tablet.addButton({ - icon: Audio.pushToTalk ? PTT_ICONS.icon : Audio.muted ? MUTE_ICONS.icon : UNMUTE_ICONS.icon, - activeIcon: Audio.pushToTalk ? PTT_ICONS.activeIcon : Audio.muted ? MUTE_ICONS.activeIcon : UNMUTE_ICONS.activeIcon, - text: TABLET_BUTTON_NAME, - sortOrder: 1 -}); - -onMuteToggled(); - -button.clicked.connect(onClicked); -tablet.screenChanged.connect(onScreenChanged); -Audio.mutedChanged.connect(onMuteToggled); -Audio.pushToTalkChanged.connect(onMuteToggled); -HMD.displayModeChanged.connect(onMuteToggled); - -Script.scriptEnding.connect(function () { - if (onAudioScreen) { - tablet.gotoHomeScreen(); - } - button.clicked.disconnect(onClicked); - tablet.screenChanged.disconnect(onScreenChanged); - Audio.mutedChanged.disconnect(onMuteToggled); - Audio.pushToTalkChanged.disconnect(onMuteToggled); - HMD.displayModeChanged.disconnect(onMuteToggled); - tablet.removeButton(button); -}); - -}()); // END LOCAL_SCOPE diff --git a/scripts/simplifiedUI/system/audioMuteOverlay.js b/scripts/simplifiedUI/system/audioMuteOverlay.js deleted file mode 100644 index 9acc5ab123..0000000000 --- a/scripts/simplifiedUI/system/audioMuteOverlay.js +++ /dev/null @@ -1,130 +0,0 @@ -// -// audioMuteOverlay.js -// -// client script that creates an overlay to provide mute feedback -// -// Created by Triplelexx on 17/03/09 -// Reworked by Seth Alves on 2019-2-17 -// 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 -// - -"use strict"; - -/* global Audio, Script, Overlays, Quat, MyAvatar, HMD */ - -(function() { // BEGIN LOCAL_SCOPE - - var lastShortTermInputLoudness = 0.0; - var lastLongTermInputLoudness = 0.0; - var sampleRate = 8.0; // Hz - - var shortTermAttackTC = Math.exp(-1.0 / (sampleRate * 0.500)); // 500 milliseconds attack - var shortTermReleaseTC = Math.exp(-1.0 / (sampleRate * 1.000)); // 1000 milliseconds release - - var longTermAttackTC = Math.exp(-1.0 / (sampleRate * 5.0)); // 5 second attack - var longTermReleaseTC = Math.exp(-1.0 / (sampleRate * 10.0)); // 10 seconds release - - var activationThreshold = 0.05; // how much louder short-term needs to be than long-term to trigger warning - - var holdReset = 2.0 * sampleRate; // 2 seconds hold - var holdCount = 0; - var warningOverlayID = null; - var pollInterval = null; - var warningText = "Muted"; - - function showWarning() { - if (warningOverlayID) { - return; - } - - if (HMD.active) { - warningOverlayID = Overlays.addOverlay("text3d", { - name: "Muted-Warning", - localPosition: { x: 0.0, y: -0.45, z: -1.0 }, - localOrientation: Quat.fromVec3Degrees({ x: 0.0, y: 0.0, z: 0.0, w: 1.0 }), - text: warningText, - textAlpha: 1, - textColor: { red: 226, green: 51, blue: 77 }, - backgroundAlpha: 0, - lineHeight: 0.042, - dimensions: { x: 0.11, y: 0.05 }, - visible: true, - ignoreRayIntersection: true, - drawInFront: true, - grabbable: false, - parentID: MyAvatar.SELF_ID, - parentJointIndex: MyAvatar.getJointIndex("_CAMERA_MATRIX") - }); - } - } - - function hideWarning() { - if (!warningOverlayID) { - return; - } - Overlays.deleteOverlay(warningOverlayID); - warningOverlayID = null; - } - - function startPoll() { - if (pollInterval) { - return; - } - pollInterval = Script.setInterval(function() { - var shortTermInputLoudness = Audio.inputLevel; - var longTermInputLoudness = shortTermInputLoudness; - - var shortTc = (shortTermInputLoudness > lastShortTermInputLoudness) ? shortTermAttackTC : shortTermReleaseTC; - var longTc = (longTermInputLoudness > lastLongTermInputLoudness) ? longTermAttackTC : longTermReleaseTC; - - shortTermInputLoudness += shortTc * (lastShortTermInputLoudness - shortTermInputLoudness); - longTermInputLoudness += longTc * (lastLongTermInputLoudness - longTermInputLoudness); - - lastShortTermInputLoudness = shortTermInputLoudness; - lastLongTermInputLoudness = longTermInputLoudness; - - if (shortTermInputLoudness > lastLongTermInputLoudness + activationThreshold) { - holdCount = holdReset; - } else { - holdCount = Math.max(holdCount - 1, 0); - } - - if (holdCount > 0) { - showWarning(); - } else { - hideWarning(); - } - }, 1000.0 / sampleRate); - } - - function stopPoll() { - if (!pollInterval) { - return; - } - Script.clearInterval(pollInterval); - pollInterval = null; - hideWarning(); - } - - function startOrStopPoll() { - if (Audio.warnWhenMuted && Audio.muted) { - startPoll(); - } else { - stopPoll(); - } - } - - function cleanup() { - stopPoll(); - } - - Script.scriptEnding.connect(cleanup); - - startOrStopPoll(); - Audio.mutedChanged.connect(startOrStopPoll); - Audio.warnWhenMutedChanged.connect(startOrStopPoll); - -}()); // END LOCAL_SCOPE diff --git a/scripts/simplifiedUI/system/audioScope.js b/scripts/simplifiedUI/system/audioScope.js deleted file mode 100644 index 81d8e8fbd4..0000000000 --- a/scripts/simplifiedUI/system/audioScope.js +++ /dev/null @@ -1,95 +0,0 @@ -"use strict"; -// -// audioScope.js -// scripts/system/ -// -// Created by Brad Hefta-Gaub on 3/10/2016 -// Copyright 2016 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// -/* global Script, Tablet, AudioScope, Audio */ - -(function () { // BEGIN LOCAL_SCOPE - - var scopeVisibile = AudioScope.getVisible(); - var scopePaused = AudioScope.getPause(); - var autoPause = false; - - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - var showScopeButton = tablet.addButton({ - icon: "icons/tablet-icons/scope.svg", - text: "Audio Scope", - isActive: scopeVisibile - }); - - var scopePauseImage = "icons/tablet-icons/scope-pause.svg"; - var scopePlayImage = "icons/tablet-icons/scope-play.svg"; - - var pauseScopeButton = tablet.addButton({ - icon: scopePaused ? scopePlayImage : scopePauseImage, - text: scopePaused ? "Unpause" : "Pause", - isActive: scopePaused - }); - - var autoPauseScopeButton = tablet.addButton({ - icon: "icons/tablet-icons/scope-auto.svg", - text: "Auto Pause", - isActive: autoPause - }); - - function setScopePause(paused) { - scopePaused = paused; - pauseScopeButton.editProperties({ - isActive: scopePaused, - icon: scopePaused ? scopePlayImage : scopePauseImage, - text: scopePaused ? "Unpause" : "Pause" - }); - AudioScope.setPause(scopePaused); - } - - showScopeButton.clicked.connect(function () { - // toggle button active state - scopeVisibile = !scopeVisibile; - showScopeButton.editProperties({ - isActive: scopeVisibile - }); - - AudioScope.setVisible(scopeVisibile); - }); - - pauseScopeButton.clicked.connect(function () { - // toggle button active state - setScopePause(!scopePaused); - }); - - autoPauseScopeButton.clicked.connect(function () { - // toggle button active state - autoPause = !autoPause; - autoPauseScopeButton.editProperties({ - isActive: autoPause, - text: autoPause ? "Auto Pause" : "Manual" - }); - }); - - Script.scriptEnding.connect(function () { - tablet.removeButton(showScopeButton); - tablet.removeButton(pauseScopeButton); - tablet.removeButton(autoPauseScopeButton); - }); - - Audio.noiseGateOpened.connect(function(){ - if (autoPause) { - setScopePause(false); - } - }); - - Audio.noiseGateClosed.connect(function(){ - // noise gate closed - if (autoPause) { - setScopePause(true); - } - }); - -}()); // END LOCAL_SCOPE \ No newline at end of file diff --git a/scripts/simplifiedUI/system/avatarFinderBeacon.js b/scripts/simplifiedUI/system/avatarFinderBeacon.js deleted file mode 100644 index 00f3d15fbb..0000000000 --- a/scripts/simplifiedUI/system/avatarFinderBeacon.js +++ /dev/null @@ -1,93 +0,0 @@ -// avatarFinderBeacon.js -// -// Created by Thijs Wenker on 12/7/16 -// Copyright 2016 High Fidelity, Inc. -// -// Shows 2km long red beams for each avatar outside of the 20 meter radius of your avatar, tries to ignore AC Agents. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - -var MIN_DISPLAY_DISTANCE = 20.0; // meters -var BEAM_COLOR = {red: 255, green: 0, blue: 0}; -var SHOW_THROUGH_WALLS = false; -var BEACON_LENGTH = 2000.0; // meters -var TRY_TO_IGNORE_AC_AGENTS = true; - -var HALF_BEACON_LENGTH = BEACON_LENGTH / 2.0; - -var beacons = {}; - -// List of .fst files used by AC scripts, that should be ignored in the script in case TRY_TO_IGNORE_AC_AGENTS is enabled -var POSSIBLE_AC_AVATARS = [ - 'http://hifi-content.s3.amazonaws.com/ozan/dev/avatars/invisible_avatar/invisible_avatar.fst', - 'http://hifi-content.s3.amazonaws.com/ozan/dev/avatars/camera_man/pod/_latest/camera_man_pod.fst' -]; - -AvatarFinderBeacon = function(avatar) { - var visible = false; - var avatarSessionUUID = avatar.sessionUUID; - this.overlay = Overlays.addOverlay('line3d', { - color: BEAM_COLOR, - dashed: false, - start: Vec3.sum(avatar.position, {x: 0, y: -HALF_BEACON_LENGTH, z: 0}), - end: Vec3.sum(avatar.position, {x: 0, y: HALF_BEACON_LENGTH, z: 0}), - rotation: {x: 0, y: 0, z: 0, w: 1}, - visible: visible, - drawInFront: SHOW_THROUGH_WALLS, - ignoreRayIntersection: true, - parentID: avatarSessionUUID, - parentJointIndex: -2 - }); - this.cleanup = function() { - Overlays.deleteOverlay(this.overlay); - }; - this.shouldShow = function() { - return Vec3.distance(MyAvatar.position, avatar.position) >= MIN_DISPLAY_DISTANCE; - }; - this.update = function() { - avatar = AvatarList.getAvatar(avatarSessionUUID); - Overlays.editOverlay(this.overlay, { - visible: this.shouldShow() - }); - }; -}; - -function updateBeacon(avatarSessionUUID) { - if (!(avatarSessionUUID in beacons)) { - var avatar = AvatarList.getAvatar(avatarSessionUUID); - if (TRY_TO_IGNORE_AC_AGENTS - && (POSSIBLE_AC_AVATARS.indexOf(avatar.skeletonModelURL) !== -1 || Vec3.length(avatar.position) === 0.0)) { - return; - } - beacons[avatarSessionUUID] = new AvatarFinderBeacon(avatar); - return; - } - beacons[avatarSessionUUID].update(); -} - -Window.domainChanged.connect(function () { - beacons = {}; -}); - -Script.update.connect(function() { - AvatarList.getAvatarIdentifiers().forEach(function(avatarSessionUUID) { - updateBeacon(avatarSessionUUID); - }); -}); - -AvatarList.avatarRemovedEvent.connect(function(avatarSessionUUID) { - if (avatarSessionUUID in beacons) { - beacons[avatarSessionUUID].cleanup(); - delete beacons[avatarSessionUUID]; - } -}); - -Script.scriptEnding.connect(function() { - for (var sessionUUID in beacons) { - if (!beacons.hasOwnProperty(sessionUUID)) { - return; - } - beacons[sessionUUID].cleanup(); - } -}); diff --git a/scripts/simplifiedUI/system/avatarapp.js b/scripts/simplifiedUI/system/avatarapp.js deleted file mode 100644 index 6439d30023..0000000000 --- a/scripts/simplifiedUI/system/avatarapp.js +++ /dev/null @@ -1,663 +0,0 @@ -"use strict"; -/*jslint vars:true, plusplus:true, forin:true*/ -/*global Tablet, Script, Entities, MyAvatar, Camera, Quat, HMD, Account, UserActivityLogger, Messages, print, - AvatarBookmarks, ContextOverlay, AddressManager -*/ -/* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ -// -// avatarapp.js -// -// Created by Alexander Ivash on April 30, 2018 -// Copyright 2016 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 -// - -(function() { // BEGIN LOCAL_SCOPE - -var AVATARAPP_QML_SOURCE = "hifi/AvatarApp.qml"; -Script.include("/~/system/libraries/controllers.js"); - -// constants from AvatarBookmarks.h -var ENTRY_AVATAR_URL = "avatarUrl"; -var ENTRY_AVATAR_ENTITIES = "avatarEntites"; -var ENTRY_AVATAR_SCALE = "avatarScale"; - -function executeLater(callback) { - Script.setTimeout(callback, 300); -} - -function isWearable(avatarEntity) { - return avatarEntity.properties.visible === true && - (avatarEntity.properties.parentID === MyAvatar.sessionUUID || avatarEntity.properties.parentID === MyAvatar.SELF_ID); -} - -function getMyAvatarWearables() { - var entitiesArray = MyAvatar.getAvatarEntitiesVariant(); - var wearablesArray = []; - - for (var i = 0; i < entitiesArray.length; ++i) { - var entity = entitiesArray[i]; - if (!isWearable(entity)) { - continue; - } - - var localRotation = entity.properties.localRotation; - entity.properties.localRotationAngles = Quat.safeEulerAngles(localRotation); - wearablesArray.push(entity); - } - - return wearablesArray; -} - -function getMyAvatar() { - var avatar = {}; - avatar[ENTRY_AVATAR_URL] = MyAvatar.skeletonModelURL; - avatar[ENTRY_AVATAR_SCALE] = MyAvatar.getAvatarScale(); - avatar[ENTRY_AVATAR_ENTITIES] = getMyAvatarWearables(); - return avatar; -} - -function getMyAvatarSettings() { - return { - dominantHand: MyAvatar.getDominantHand(), - hmdAvatarAlignmentType: MyAvatar.getHmdAvatarAlignmentType(), - collisionsEnabled: MyAvatar.getCollisionsEnabled(), - otherAvatarsCollisionsEnabled: MyAvatar.getOtherAvatarsCollisionsEnabled(), - collisionSoundUrl : MyAvatar.collisionSoundURL, - animGraphUrl: MyAvatar.getAnimGraphUrl(), - animGraphOverrideUrl : MyAvatar.getAnimGraphOverrideUrl(), - }; -} - -function updateAvatarWearables(avatar, callback, wearablesOverride) { - executeLater(function() { - var wearables = wearablesOverride ? wearablesOverride : getMyAvatarWearables(); - avatar[ENTRY_AVATAR_ENTITIES] = wearables; - - sendToQml({'method' : 'wearablesUpdated', 'wearables' : wearables}); - sendToQml({ 'method' : 'wearablesFrozenChanged', 'wearablesFrozen' : getWearablesFrozen()}); - - if(callback) - callback(); - }); -} - -var adjustWearables = { - opened : false, - cameraMode : '', - setOpened : function(value) { - if(this.opened !== value) { - if(value) { - this.cameraMode = Camera.mode; - - if(!HMD.active) { - Camera.mode = 'mirror'; - } - } else { - Camera.mode = this.cameraMode; - } - - this.opened = value; - } - } -}; - -var currentAvatarWearablesBackup = null; -var currentAvatar = null; -var currentAvatarSettings = getMyAvatarSettings(); - -var notifyScaleChanged = true; -function onTargetScaleChanged() { - if(currentAvatar.scale !== MyAvatar.getAvatarScale()) { - currentAvatar.scale = MyAvatar.getAvatarScale(); - if(notifyScaleChanged) { - sendToQml({'method' : 'scaleChanged', 'value' : currentAvatar.scale}); - } - } -} - -function onSkeletonModelURLChanged() { - if(currentAvatar || (currentAvatar.skeletonModelURL !== MyAvatar.skeletonModelURL)) { - fromQml({'method' : 'getAvatars'}); - } -} - -function onDominantHandChanged(dominantHand) { - if(currentAvatarSettings.dominantHand !== dominantHand) { - currentAvatarSettings.dominantHand = dominantHand; - sendToQml({'method' : 'settingChanged', 'name' : 'dominantHand', 'value' : dominantHand}); - } -} - -function onHmdAvatarAlignmentTypeChanged(type) { - if (currentAvatarSettings.hmdAvatarAlignmentType !== type) { - currentAvatarSettings.hmdAvatarAlignmentType = type; - sendToQml({'method' : 'settingChanged', 'name' : 'hmdAvatarAlignmentType', 'value' : type}); - } -} - -function onCollisionsEnabledChanged(enabled) { - if(currentAvatarSettings.collisionsEnabled !== enabled) { - currentAvatarSettings.collisionsEnabled = enabled; - sendToQml({'method' : 'settingChanged', 'name' : 'collisionsEnabled', 'value' : enabled}); - } -} - -function onOtherAvatarsCollisionsEnabledChanged(enabled) { - if (currentAvatarSettings.otherAvatarsCollisionsEnabled !== enabled) { - currentAvatarSettings.otherAvatarsCollisionsEnabled = enabled; - sendToQml({ 'method': 'settingChanged', 'name': 'otherAvatarsCollisionsEnabled', 'value': enabled }); - } -} - -function onNewCollisionSoundUrl(url) { - if(currentAvatarSettings.collisionSoundUrl !== url) { - currentAvatarSettings.collisionSoundUrl = url; - sendToQml({'method' : 'settingChanged', 'name' : 'collisionSoundUrl', 'value' : url}); - } -} - -function onAnimGraphUrlChanged(url) { - if (currentAvatarSettings.animGraphUrl !== url) { - currentAvatarSettings.animGraphUrl = url; - sendToQml({ 'method': 'settingChanged', 'name': 'animGraphUrl', 'value': currentAvatarSettings.animGraphUrl }); - - if (currentAvatarSettings.animGraphOverrideUrl !== MyAvatar.getAnimGraphOverrideUrl()) { - currentAvatarSettings.animGraphOverrideUrl = MyAvatar.getAnimGraphOverrideUrl(); - sendToQml({ 'method': 'settingChanged', 'name': 'animGraphOverrideUrl', - 'value': currentAvatarSettings.animGraphOverrideUrl }); - } - } -} - -var selectedAvatarEntityID = null; -var grabbedAvatarEntityChangeNotifier = null; - -var MARKETPLACE_PURCHASES_QML_PATH = "hifi/commerce/wallet/Wallet.qml"; -var MARKETPLACE_URL = Account.metaverseServerURL + "/marketplace"; -var MARKETPLACES_INJECT_SCRIPT_URL = Script.resolvePath("html/js/marketplacesInject.js"); - -function getWearablesFrozen() { - var wearablesFrozen = true; - var wearablesArray = getMyAvatarWearables(); - wearablesArray.forEach(function(wearable) { - if (isGrabbable(wearable.id)) { - wearablesFrozen = false; - } - }); - - return wearablesFrozen; -} - -function freezeWearables() { - var wearablesArray = getMyAvatarWearables(); - wearablesArray.forEach(function(wearable) { - setGrabbable(wearable.id, false); - }); -} - -function unfreezeWearables() { - var wearablesArray = getMyAvatarWearables(); - wearablesArray.forEach(function(wearable) { - setGrabbable(wearable.id, true); - }); -} - - -function fromQml(message) { // messages are {method, params}, like json-rpc. See also sendToQml. - switch (message.method) { - case 'getAvatars': - currentAvatar = getMyAvatar(); - currentAvatarSettings = getMyAvatarSettings(); - - message.data = { - 'bookmarks' : AvatarBookmarks.getBookmarks(), - 'displayName' : MyAvatar.displayName, - 'currentAvatar' : currentAvatar, - 'currentAvatarSettings' : currentAvatarSettings - }; - - for(var bookmarkName in message.data.bookmarks) { - var bookmark = message.data.bookmarks[bookmarkName]; - - if (bookmark.avatarEntites) { - bookmark.avatarEntites.forEach(function(avatarEntity) { - avatarEntity.properties.localRotationAngles = Quat.safeEulerAngles(avatarEntity.properties.localRotation); - }); - } - } - - sendToQml(message); - break; - case 'selectAvatar': - Entities.addingWearable.disconnect(onAddingWearable); - Entities.deletingWearable.disconnect(onDeletingWearable); - AvatarBookmarks.loadBookmark(message.name); - Entities.addingWearable.connect(onAddingWearable); - Entities.deletingWearable.connect(onDeletingWearable); - sendToQml({ 'method' : 'wearablesFrozenChanged', 'wearablesFrozen' : getWearablesFrozen()}); - break; - case 'deleteAvatar': - AvatarBookmarks.removeBookmark(message.name); - break; - case 'addAvatar': - AvatarBookmarks.addBookmark(message.name); - break; - case 'adjustWearable': - if(message.properties.localRotationAngles) { - message.properties.localRotation = Quat.fromVec3Degrees(message.properties.localRotationAngles); - } - - Entities.editEntity(message.entityID, message.properties); - message.properties = Entities.getEntityProperties(message.entityID, Object.keys(message.properties)); - - if(message.properties.localRotation) { - message.properties.localRotationAngles = Quat.safeEulerAngles(message.properties.localRotation); - } - - sendToQml({'method' : 'wearableUpdated', 'entityID' : message.entityID, wearableIndex : message.wearableIndex, properties : message.properties, updateUI : false}); - break; - case 'adjustWearablesOpened': - currentAvatarWearablesBackup = getMyAvatarWearables(); - adjustWearables.setOpened(true); - unfreezeWearables(); - - Entities.mousePressOnEntity.connect(onSelectedEntity); - Messages.subscribe('Hifi-Object-Manipulation'); - Messages.messageReceived.connect(handleWearableMessages); - break; - case 'adjustWearablesClosed': - if(!message.save) { - // revert changes using snapshot of wearables - if(currentAvatarWearablesBackup !== null) { - AvatarBookmarks.updateAvatarEntities(currentAvatarWearablesBackup); - updateAvatarWearables(currentAvatar, null, currentAvatarWearablesBackup); - } - } else { - sendToQml({'method' : 'updateAvatarInBookmarks'}); - } - - adjustWearables.setOpened(false); - ensureWearableSelected(null); - Entities.mousePressOnEntity.disconnect(onSelectedEntity); - Messages.messageReceived.disconnect(handleWearableMessages); - Messages.unsubscribe('Hifi-Object-Manipulation'); - break; - case 'addWearable': - - var joints = MyAvatar.getJointNames(); - var hipsIndex = -1; - - for(var i = 0; i < joints.length; ++i) { - if(joints[i] === 'Hips') { - hipsIndex = i; - break; - } - } - - var properties = { - name: "Custom wearable", - type: "Model", - modelURL: message.url, - parentID: MyAvatar.sessionUUID, - relayParentJoints: false, - parentJointIndex: hipsIndex - }; - - Entities.addingWearable.disconnect(onAddingWearable); - var entityID = Entities.addEntity(properties, true); - Entities.addingWearable.connect(onAddingWearable); - - updateAvatarWearables(currentAvatar, function() { - onSelectedEntity(entityID); - }); - break; - case 'selectWearable': - ensureWearableSelected(message.entityID); - break; - case 'deleteWearable': - - Entities.deletingWearable.disconnect(onDeletingWearable); - Entities.deleteEntity(message.entityID); - Entities.deletingWearable.connect(onDeletingWearable); - - updateAvatarWearables(currentAvatar); - break; - case 'changeDisplayName': - if (MyAvatar.displayName !== message.displayName) { - MyAvatar.displayName = message.displayName; - UserActivityLogger.palAction("display_name_change", message.displayName); - } - break; - case 'applyExternalAvatar': - var currentAvatarURL = MyAvatar.getFullAvatarURLFromPreferences(); - if(currentAvatarURL !== message.avatarURL) { - MyAvatar.useFullAvatarURL(message.avatarURL); - sendToQml({'method' : 'externalAvatarApplied', 'avatarURL' : message.avatarURL}); - } - break; - case 'navigate': - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - if(message.url.indexOf('app://') === 0) { - if (message.url === 'app://marketplace') { - tablet.gotoWebScreen(MARKETPLACE_URL, MARKETPLACES_INJECT_SCRIPT_URL); - } else if (message.url === 'app://purchases') { - tablet.pushOntoStack(MARKETPLACE_PURCHASES_QML_PATH); - } - - } else if(message.url.indexOf('hifi://') === 0) { - AddressManager.handleLookupString(message.url, false); - } else if(message.url.indexOf('https://') === 0 || message.url.indexOf('http://') === 0) { - tablet.gotoWebScreen(message.url, MARKETPLACES_INJECT_SCRIPT_URL); - } - - break; - case 'setScale': - notifyScaleChanged = false; - MyAvatar.setAvatarScale(message.avatarScale); - currentAvatar.avatarScale = message.avatarScale; - notifyScaleChanged = true; - break; - case 'revertScale': - MyAvatar.setAvatarScale(message.avatarScale); - currentAvatar.avatarScale = message.avatarScale; - break; - case 'saveSettings': - MyAvatar.setAvatarScale(message.avatarScale); - currentAvatar.avatarScale = message.avatarScale; - - MyAvatar.setDominantHand(message.settings.dominantHand); - MyAvatar.setHmdAvatarAlignmentType(message.settings.hmdAvatarAlignmentType); - MyAvatar.setOtherAvatarsCollisionsEnabled(message.settings.otherAvatarsCollisionsEnabled); - MyAvatar.setCollisionsEnabled(message.settings.collisionsEnabled); - MyAvatar.collisionSoundURL = message.settings.collisionSoundUrl; - MyAvatar.setAnimGraphOverrideUrl(message.settings.animGraphOverrideUrl); - - currentAvatarSettings = getMyAvatarSettings(); - break; - case 'toggleWearablesFrozen': - var wearablesFrozen = getWearablesFrozen(); - wearablesFrozen = !wearablesFrozen; - if (wearablesFrozen) { - freezeWearables(); - } else { - unfreezeWearables(); - } - sendToQml({'method' : 'wearablesFrozenChanged', 'wearablesFrozen' : wearablesFrozen}); - break; - default: - print('Unrecognized message from AvatarApp.qml'); - } -} - -function isGrabbable(entityID) { - if(entityID === null) { - return false; - } - - var properties = Entities.getEntityProperties(entityID, ['avatarEntity', 'grab.grabbable']); - if (properties.avatarEntity) { - return properties.grab.grabbable; - } - - return false; -} - -function setGrabbable(entityID, grabbable) { - var properties = Entities.getEntityProperties(entityID, ['avatarEntity', 'grab.grabbable']); - if (properties.avatarEntity && properties.grab.grabbable != grabbable) { - var editProps = { grab: { grabbable: grabbable }}; - Entities.editEntity(entityID, editProps); - sendToQml({ 'method' : 'wearablesFrozenChanged', 'wearablesFrozen' : getWearablesFrozen()}); - } -} - -function ensureWearableSelected(entityID) { - if(selectedAvatarEntityID !== entityID) { - if(grabbedAvatarEntityChangeNotifier !== null) { - Script.clearInterval(grabbedAvatarEntityChangeNotifier); - grabbedAvatarEntityChangeNotifier = null; - } - selectedAvatarEntityID = entityID; - return true; - } - - return false; -} - -function isEntityBeingWorn(entityID) { - return Entities.getEntityProperties(entityID, 'parentID').parentID === MyAvatar.sessionUUID; -} - -function onSelectedEntity(entityID, pointerEvent) { - if(selectedAvatarEntityID !== entityID && isEntityBeingWorn(entityID)) - { - if(ensureWearableSelected(entityID)) { - sendToQml({'method' : 'selectAvatarEntity', 'entityID' : selectedAvatarEntityID}); - } - } -} - -function onAddingWearable(entityID) { - updateAvatarWearables(currentAvatar, function() { - sendToQml({'method' : 'updateAvatarInBookmarks'}); - }); - sendToQml({ 'method' : 'wearablesFrozenChanged', 'wearablesFrozen' : getWearablesFrozen()}); -} - -function onDeletingWearable(entityID) { - updateAvatarWearables(currentAvatar, function() { - sendToQml({'method' : 'updateAvatarInBookmarks'}); - }); - sendToQml({ 'method' : 'wearablesFrozenChanged', 'wearablesFrozen' : getWearablesFrozen()}); -} - -function handleWearableMessages(channel, message, sender) { - if (channel !== 'Hifi-Object-Manipulation') { - return; - } - - var parsedMessage = null; - - try { - parsedMessage = JSON.parse(message); - } catch (e) { - return; - } - - var entityID = parsedMessage.grabbedEntity; - - var updateWearable = function() { - // for some reasons Entities.getEntityProperties returns more than was asked.. - var propertyNames = ['localPosition', 'localRotation', 'dimensions', 'naturalDimensions']; - var entityProperties = Entities.getEntityProperties(selectedAvatarEntityID, propertyNames); - var properties = {}; - - propertyNames.forEach(function(propertyName) { - properties[propertyName] = entityProperties[propertyName]; - }); - - properties.localRotationAngles = Quat.safeEulerAngles(properties.localRotation); - sendToQml({'method' : 'wearableUpdated', 'entityID' : selectedAvatarEntityID, - 'wearableIndex' : -1, 'properties' : properties, updateUI : true}); - - }; - - if(parsedMessage.action === 'grab') { - if(selectedAvatarEntityID !== entityID) { - ensureWearableSelected(entityID); - sendToQml({'method' : 'selectAvatarEntity', 'entityID' : selectedAvatarEntityID}); - } - - grabbedAvatarEntityChangeNotifier = Script.setInterval(updateWearable, 1000); - } else if(parsedMessage.action === 'release') { - if(grabbedAvatarEntityChangeNotifier !== null) { - Script.clearInterval(grabbedAvatarEntityChangeNotifier); - grabbedAvatarEntityChangeNotifier = null; - updateWearable(); - } - } -} - -function sendToQml(message) { - tablet.sendToQml(message); -} - -function onBookmarkLoaded(bookmarkName) { - executeLater(function() { - currentAvatar = getMyAvatar(); - sendToQml({'method' : 'bookmarkLoaded', 'data' : {'name' : bookmarkName, 'currentAvatar' : currentAvatar} }); - }); -} - -function onBookmarkDeleted(bookmarkName) { - sendToQml({'method' : 'bookmarkDeleted', 'name' : bookmarkName}); -} - -function onBookmarkAdded(bookmarkName) { - var bookmark = AvatarBookmarks.getBookmark(bookmarkName); - bookmark.avatarEntites.forEach(function(avatarEntity) { - avatarEntity.properties.localRotationAngles = Quat.safeEulerAngles(avatarEntity.properties.localRotation); - }); - - sendToQml({ 'method': 'bookmarkAdded', 'bookmarkName': bookmarkName, 'bookmark': bookmark }); -} - -// -// Manage the connection between the button and the window. -// -var button; -var buttonName = "AVATAR"; -var tablet = null; - -function startup() { - tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - button = tablet.addButton({ - text: buttonName, - icon: "icons/tablet-icons/avatar-i.svg", - activeIcon: "icons/tablet-icons/avatar-a.svg", - sortOrder: 7 - }); - button.clicked.connect(onTabletButtonClicked); - tablet.screenChanged.connect(onTabletScreenChanged); -} - -startup(); - -var isWired = false; -function off() { - if(adjustWearables.opened) { - adjustWearables.setOpened(false); - ensureWearableSelected(null); - Entities.mousePressOnEntity.disconnect(onSelectedEntity); - - Messages.messageReceived.disconnect(handleWearableMessages); - Messages.unsubscribe('Hifi-Object-Manipulation'); - } - - if (isWired) { // It is not ok to disconnect these twice, hence guard. - isWired = false; - - AvatarBookmarks.bookmarkLoaded.disconnect(onBookmarkLoaded); - AvatarBookmarks.bookmarkDeleted.disconnect(onBookmarkDeleted); - AvatarBookmarks.bookmarkAdded.disconnect(onBookmarkAdded); - - Entities.addingWearable.disconnect(onAddingWearable); - Entities.deletingWearable.disconnect(onDeletingWearable); - MyAvatar.skeletonModelURLChanged.disconnect(onSkeletonModelURLChanged); - MyAvatar.dominantHandChanged.disconnect(onDominantHandChanged); - MyAvatar.hmdAvatarAlignmentTypeChanged.disconnect(onHmdAvatarAlignmentTypeChanged); - MyAvatar.collisionsEnabledChanged.disconnect(onCollisionsEnabledChanged); - MyAvatar.otherAvatarsCollisionsEnabledChanged.disconnect(onOtherAvatarsCollisionsEnabledChanged); - MyAvatar.newCollisionSoundURL.disconnect(onNewCollisionSoundUrl); - MyAvatar.animGraphUrlChanged.disconnect(onAnimGraphUrlChanged); - MyAvatar.targetScaleChanged.disconnect(onTargetScaleChanged); - } -} - -function on() { - - if (!isWired) { // It is not ok to connect these twice, hence guard. - isWired = true; - - AvatarBookmarks.bookmarkLoaded.connect(onBookmarkLoaded); - AvatarBookmarks.bookmarkDeleted.connect(onBookmarkDeleted); - AvatarBookmarks.bookmarkAdded.connect(onBookmarkAdded); - - Entities.addingWearable.connect(onAddingWearable); - Entities.deletingWearable.connect(onDeletingWearable); - MyAvatar.skeletonModelURLChanged.connect(onSkeletonModelURLChanged); - MyAvatar.dominantHandChanged.connect(onDominantHandChanged); - MyAvatar.hmdAvatarAlignmentTypeChanged.connect(onHmdAvatarAlignmentTypeChanged); - MyAvatar.collisionsEnabledChanged.connect(onCollisionsEnabledChanged); - MyAvatar.otherAvatarsCollisionsEnabledChanged.connect(onOtherAvatarsCollisionsEnabledChanged); - MyAvatar.newCollisionSoundURL.connect(onNewCollisionSoundUrl); - MyAvatar.animGraphUrlChanged.connect(onAnimGraphUrlChanged); - MyAvatar.targetScaleChanged.connect(onTargetScaleChanged); - } -} - -function onTabletButtonClicked() { - if (onAvatarAppScreen) { - // for toolbar-mode: go back to home screen, this will close the window. - tablet.gotoHomeScreen(); - } else { - ContextOverlay.enabled = false; - tablet.loadQMLSource(AVATARAPP_QML_SOURCE); - } -} -var hasEventBridge = false; -function wireEventBridge(on) { - if (on) { - if (!hasEventBridge) { - tablet.fromQml.connect(fromQml); - hasEventBridge = true; - } - } else { - if (hasEventBridge) { - tablet.fromQml.disconnect(fromQml); - hasEventBridge = false; - } - } -} - -var onAvatarAppScreen = false; -function onTabletScreenChanged(type, url) { - var onAvatarAppScreenNow = (type === "QML" && url === AVATARAPP_QML_SOURCE); - wireEventBridge(onAvatarAppScreenNow); - // for toolbar mode: change button to active when window is first openend, false otherwise. - button.editProperties({isActive: onAvatarAppScreenNow}); - - if (!onAvatarAppScreen && onAvatarAppScreenNow) { - on(); - } else if(onAvatarAppScreen && !onAvatarAppScreenNow) { - off(); - } - - onAvatarAppScreen = onAvatarAppScreenNow; - - if(onAvatarAppScreenNow) { - sendToQml({ 'method' : 'initialize', 'data' : { jointNames : MyAvatar.getJointNames() }}); - sendToQml({ 'method' : 'wearablesFrozenChanged', 'wearablesFrozen' : getWearablesFrozen()}); - } -} - -function shutdown() { - if (onAvatarAppScreen) { - tablet.gotoHomeScreen(); - } - button.clicked.disconnect(onTabletButtonClicked); - tablet.removeButton(button); - tablet.screenChanged.disconnect(onTabletScreenChanged); - - off(); -} - -// -// Cleanup. -// -Script.scriptEnding.connect(shutdown); - -}()); // END LOCAL_SCOPE diff --git a/scripts/simplifiedUI/system/away.js b/scripts/simplifiedUI/system/away.js deleted file mode 100644 index 6293c0c452..0000000000 --- a/scripts/simplifiedUI/system/away.js +++ /dev/null @@ -1,387 +0,0 @@ -"use strict"; - -// -// away.js -// -// examples -// -// Created by Howard Stearns 11/3/15 -// Copyright 2015 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 -// -// Goes into "paused" when the '.' key (and automatically when started in HMD), and normal when pressing any key. -// See MAIN CONTROL, below, for what "paused" actually does. - -/* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ - -(function() { // BEGIN LOCAL_SCOPE - -var BASIC_TIMER_INTERVAL = 50; // 50ms = 20hz -var OVERLAY_WIDTH = 1920; -var OVERLAY_HEIGHT = 1080; -var OVERLAY_DATA = { - width: OVERLAY_WIDTH, - height: OVERLAY_HEIGHT, - imageURL: Script.resolvePath("assets/images/Overlay-Viz-blank.png"), - emissive: true, - drawInFront: true, - alpha: 1 -}; -var AVATAR_MOVE_FOR_ACTIVE_DISTANCE = 0.8; // meters -- no longer away if avatar moves this far while away - -var CAMERA_MATRIX = -7; - -var OVERLAY_DATA_HMD = { - localPosition: {x: 0, y: 0, z: -1 * MyAvatar.sensorToWorldScale}, - localRotation: {x: 0, y: 0, z: 0, w: 1}, - width: OVERLAY_WIDTH, - height: OVERLAY_HEIGHT, - url: Script.resolvePath("assets/images/Overlay-Viz-blank.png"), - color: {red: 255, green: 255, blue: 255}, - alpha: 1, - scale: 2 * MyAvatar.sensorToWorldScale, - emissive: true, - drawInFront: true, - parentID: MyAvatar.SELF_ID, - parentJointIndex: CAMERA_MATRIX, - ignorePickIntersection: true -}; - -var AWAY_INTRO = { - url: "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/kneel.fbx", - playbackRate: 30.0, - loopFlag: false, - startFrame: 0.0, - endFrame: 83.0 -}; - -// MAIN CONTROL -var isEnabled = true; -var wasMuted; // unknonwn? -var isAway = false; // we start in the un-away state -var eventMappingName = "io.highfidelity.away"; // goActive on hand controller button events, too. -var eventMapping = Controller.newMapping(eventMappingName); -var avatarPosition = MyAvatar.position; -var wasHmdMounted = HMD.mounted; -var previousBubbleState = Users.getIgnoreRadiusEnabled(); - -var enterAwayStateWhenFocusLostInVR = HMD.enterAwayStateWhenFocusLostInVR; - -// some intervals we may create/delete -var avatarMovedInterval; - - -// prefetch the kneel animation and hold a ref so it's always resident in memory when we need it. -var _animation = AnimationCache.prefetch(AWAY_INTRO.url); - -function playAwayAnimation() { - MyAvatar.overrideAnimation(AWAY_INTRO.url, - AWAY_INTRO.playbackRate, - AWAY_INTRO.loopFlag, - AWAY_INTRO.startFrame, - AWAY_INTRO.endFrame); -} - -function stopAwayAnimation() { - MyAvatar.restoreAnimation(); -} - -// OVERLAY -var overlay = Overlays.addOverlay("image", OVERLAY_DATA); -var overlayHMD = Overlays.addOverlay("image3d", OVERLAY_DATA_HMD); - -function showOverlay() { - if (HMD.active) { - // make sure desktop version is hidden - Overlays.editOverlay(overlay, { visible: false }); - Overlays.editOverlay(overlayHMD, { visible: true }); - } else { - // make sure HMD is hidden - Overlays.editOverlay(overlayHMD, { visible: false }); - - // Update for current screen size, keeping overlay proportions constant. - var screen = Controller.getViewportDimensions(); - - // keep the overlay it's natural size and always center it... - Overlays.editOverlay(overlay, { - visible: true, - x: ((screen.x - OVERLAY_WIDTH) / 2), - y: ((screen.y - OVERLAY_HEIGHT) / 2) - }); - } -} - -function hideOverlay() { - Overlays.editOverlay(overlay, {visible: false}); - Overlays.editOverlay(overlayHMD, {visible: false}); -} - -hideOverlay(); - -function maybeMoveOverlay() { - if (isAway) { - // if we switched from HMD to Desktop, make sure to hide our HUD overlay and show the - // desktop overlay - if (!HMD.active) { - showOverlay(); // this will also recenter appropriately - } - - if (HMD.active) { - - var sensorScaleFactor = MyAvatar.sensorToWorldScale; - var localPosition = {x: 0, y: 0, z: -1 * sensorScaleFactor}; - Overlays.editOverlay(overlayHMD, { visible: true, localPosition: localPosition, scale: 2 * sensorScaleFactor }); - - // make sure desktop version is hidden - Overlays.editOverlay(overlay, { visible: false }); - - // also remember avatar position - avatarPosition = MyAvatar.position; - - } - } -} - -function ifAvatarMovedGoActive() { - var newAvatarPosition = MyAvatar.position; - if (Vec3.distance(newAvatarPosition, avatarPosition) > AVATAR_MOVE_FOR_ACTIVE_DISTANCE) { - goActive(); - } - avatarPosition = newAvatarPosition; -} - -function goAway(fromStartup) { - if (!isEnabled || isAway) { - return; - } - - // If we're entering away mode from some other state than startup, then we create our move timer immediately. - // However if we're just stating up, we need to delay this process so that we don't think the initial teleport - // is actually a move. - if (fromStartup === undefined || fromStartup === false) { - avatarMovedInterval = Script.setInterval(ifAvatarMovedGoActive, BASIC_TIMER_INTERVAL); - } else { - var WAIT_FOR_MOVE_ON_STARTUP = 3000; // 3 seconds - Script.setTimeout(function() { - avatarMovedInterval = Script.setInterval(ifAvatarMovedGoActive, BASIC_TIMER_INTERVAL); - }, WAIT_FOR_MOVE_ON_STARTUP); - } - - previousBubbleState = Users.getIgnoreRadiusEnabled(); - if (!previousBubbleState) { - Users.toggleIgnoreRadius(); - } - UserActivityLogger.privacyShieldToggled(Users.getIgnoreRadiusEnabled()); - UserActivityLogger.toggledAway(true); - MyAvatar.isAway = true; -} - -function goActive() { - if (!isAway) { - return; - } - - UserActivityLogger.toggledAway(false); - MyAvatar.isAway = false; - - if (Users.getIgnoreRadiusEnabled() !== previousBubbleState) { - Users.toggleIgnoreRadius(); - UserActivityLogger.privacyShieldToggled(Users.getIgnoreRadiusEnabled()); - } - - if (!Window.hasFocus()) { - Window.setFocus(); - } -} - -MyAvatar.wentAway.connect(setAwayProperties); -MyAvatar.wentActive.connect(setActiveProperties); - -function setAwayProperties() { - isAway = true; - wasMuted = Audio.muted; - if (!wasMuted) { - Audio.muted = !Audio.muted; - } - MyAvatar.setEnableMeshVisible(false); // just for our own display, without changing point of view - playAwayAnimation(); // animation is still seen by others - showOverlay(); - - HMD.requestShowHandControllers(); - - // tell the Reticle, we want to stop capturing the mouse until we come back - Reticle.allowMouseCapture = false; - // Allow users to find their way to other applications, our menus, etc. - // For desktop, that means we want the reticle visible. - // For HMD, the hmd preview will show the system mouse because of allowMouseCapture, - // but we want to turn off our Reticle so that we don't get two in preview and a stuck one in headset. - Reticle.visible = !HMD.active; - wasHmdMounted = HMD.mounted; // always remember the correct state - - avatarPosition = MyAvatar.position; -} - -function setActiveProperties() { - isAway = false; - if (Audio.muted && !wasMuted) { - Audio.muted = false; - } - MyAvatar.setEnableMeshVisible(true); // IWBNI we respected Developer->Avatar->Draw Mesh setting. - stopAwayAnimation(); - - HMD.requestHideHandControllers(); - - // update the UI sphere to be centered about the current HMD orientation. - HMD.centerUI(); - - // forget about any IK joint limits - MyAvatar.clearIKJointLimitHistory(); - - // update the avatar hips to point in the same direction as the HMD orientation. - MyAvatar.centerBody(); - - hideOverlay(); - - // tell the Reticle, we are ready to capture the mouse again and it should be visible - Reticle.allowMouseCapture = true; - Reticle.visible = true; - if (HMD.active) { - Reticle.position = HMD.getHUDLookAtPosition2D(); - } - wasHmdMounted = HMD.mounted; // always remember the correct state - - Script.clearInterval(avatarMovedInterval); -} - -function maybeGoActive(event) { - if (event.isAutoRepeat) { // isAutoRepeat is true when held down (or when Windows feels like it) - return; - } - if (!isAway && (event.text === 'ESC')) { - goAway(); - } else { - goActive(); - } -} - -var wasHmdActive = HMD.active; -var wasMouseCaptured = Reticle.mouseCaptured; - -function maybeGoAway() { - // If our active state change (went to or from HMD mode), and we are now in the HMD, go into away - if (HMD.active !== wasHmdActive) { - wasHmdActive = !wasHmdActive; - if (wasHmdActive) { - goAway(); - return; - } - } - - // If the mouse has gone from captured, to non-captured state, then it likely means the person is still in the HMD, - // but tabbed away from the application (meaning they don't have mouse control) and they likely want to go into - // an away state - if (Reticle.mouseCaptured !== wasMouseCaptured) { - wasMouseCaptured = !wasMouseCaptured; - if (!wasMouseCaptured) { - if (enterAwayStateWhenFocusLostInVR) { - goAway(); - return; - } - } - } - - // If you've removed your HMD from your head, and we can detect it, we will also go away... - if (HMD.mounted !== wasHmdMounted) { - wasHmdMounted = HMD.mounted; - print("HMD mounted changed..."); - - // We're putting the HMD on... switch to those devices - if (HMD.mounted) { - print("NOW mounted..."); - } else { - print("HMD NOW un-mounted..."); - - if (HMD.active) { - goAway(); - return; - } - } - } -} - -function setEnabled(value) { - if (!value) { - goActive(); - } - isEnabled = value; -} - -function checkAudioToggled() { - if (isAway && !Audio.muted) { - goActive(); - } -} - - -var CHANNEL_AWAY_ENABLE = "Hifi-Away-Enable"; -var handleMessage = function(channel, message, sender) { - if (channel === CHANNEL_AWAY_ENABLE && sender === MyAvatar.sessionUUID) { - print("away.js | Got message on Hifi-Away-Enable: ", message); - setEnabled(message === 'enable'); - } -}; -Messages.subscribe(CHANNEL_AWAY_ENABLE); -Messages.messageReceived.connect(handleMessage); - -var maybeIntervalTimer = Script.setInterval(function() { - maybeMoveOverlay(); - maybeGoAway(); - checkAudioToggled(); -}, BASIC_TIMER_INTERVAL); - - -Controller.mousePressEvent.connect(goActive); -Controller.keyPressEvent.connect(maybeGoActive); -// Note peek() so as to not interfere with other mappings. -eventMapping.from(Controller.Standard.LeftPrimaryThumb).peek().to(goActive); -eventMapping.from(Controller.Standard.RightPrimaryThumb).peek().to(goActive); -eventMapping.from(Controller.Standard.LeftSecondaryThumb).peek().to(goActive); -eventMapping.from(Controller.Standard.RightSecondaryThumb).peek().to(goActive); -eventMapping.from(Controller.Standard.LT).peek().to(goActive); -eventMapping.from(Controller.Standard.LB).peek().to(goActive); -eventMapping.from(Controller.Standard.LS).peek().to(goActive); -eventMapping.from(Controller.Standard.LeftGrip).peek().to(goActive); -eventMapping.from(Controller.Standard.RT).peek().to(goActive); -eventMapping.from(Controller.Standard.RB).peek().to(goActive); -eventMapping.from(Controller.Standard.RS).peek().to(goActive); -eventMapping.from(Controller.Standard.RightGrip).peek().to(goActive); -eventMapping.from(Controller.Standard.Back).peek().to(goActive); -eventMapping.from(Controller.Standard.Start).peek().to(goActive); -Controller.enableMapping(eventMappingName); - -function awayStateWhenFocusLostInVRChanged(enabled) { - enterAwayStateWhenFocusLostInVR = enabled; -} - -Script.scriptEnding.connect(function () { - Script.clearInterval(maybeIntervalTimer); - goActive(); - HMD.awayStateWhenFocusLostInVRChanged.disconnect(awayStateWhenFocusLostInVRChanged); - Controller.disableMapping(eventMappingName); - Controller.mousePressEvent.disconnect(goActive); - Controller.keyPressEvent.disconnect(maybeGoActive); - Messages.messageReceived.disconnect(handleMessage); - Messages.unsubscribe(CHANNEL_AWAY_ENABLE); -}); - -HMD.awayStateWhenFocusLostInVRChanged.connect(awayStateWhenFocusLostInVRChanged); - -if (HMD.active && !HMD.mounted) { - print("Starting script, while HMD is active and not mounted..."); - goAway(true); -} - - -}()); // END LOCAL_SCOPE diff --git a/scripts/simplifiedUI/system/bubble.js b/scripts/simplifiedUI/system/bubble.js deleted file mode 100644 index eca3b3dcd4..0000000000 --- a/scripts/simplifiedUI/system/bubble.js +++ /dev/null @@ -1,206 +0,0 @@ -"use strict"; - -// -// bubble.js -// scripts/system/ -// -// Created by Brad Hefta-Gaub on 11/18/2016 -// Copyright 2016 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// -/* global Script, Users, Overlays, AvatarList, Controller, Camera, getControllerWorldLocation, UserActivityLogger */ - -(function () { // BEGIN LOCAL_SCOPE - var button; - // Used for animating and disappearing the bubble - var bubbleOverlayTimestamp; - // Used for rate limiting the bubble sound - var lastBubbleSoundTimestamp = 0; - // Affects bubble height - var BUBBLE_HEIGHT_SCALE = 0.15; - // The bubble model itself - var bubbleOverlay = Overlays.addOverlay("model", { - url: Script.resolvePath("assets/models/Bubble-v14.fbx"), // If you'd like to change the model, modify this line (and the dimensions below) - dimensions: { x: MyAvatar.sensorToWorldScale, y: 0.75 * MyAvatar.sensorToWorldScale, z: MyAvatar.sensorToWorldScale }, - position: { x: MyAvatar.position.x, y: -MyAvatar.scale * 2 + MyAvatar.position.y + MyAvatar.scale * BUBBLE_HEIGHT_SCALE, z: MyAvatar.position.z }, - rotation: Quat.multiply(MyAvatar.orientation, Quat.fromVec3Degrees({x: 0.0, y: 180.0, z: 0.0})), - scale: { x: 2 , y: MyAvatar.scale * 0.5 + 0.5, z: 2 }, - visible: false, - ignoreRayIntersection: true - }); - // The bubble activation sound - var bubbleActivateSound = SoundCache.getSound(Script.resolvePath("assets/sounds/bubble.wav")); - // Is the update() function connected? - var updateConnected = false; - - var BUBBLE_VISIBLE_DURATION_MS = 3000; - var BUBBLE_RAISE_ANIMATION_DURATION_MS = 750; - var BUBBLE_SOUND_RATE_LIMIT_MS = 15000; - - // Hides the bubble model overlay - function hideOverlays() { - Overlays.editOverlay(bubbleOverlay, { - visible: false - }); - } - - // Make the bubble overlay visible, set its position, and play the sound - function createOverlays() { - var nowTimestamp = Date.now(); - if (nowTimestamp - lastBubbleSoundTimestamp >= BUBBLE_SOUND_RATE_LIMIT_MS) { - Audio.playSound(bubbleActivateSound, { - position: { x: MyAvatar.position.x, y: MyAvatar.position.y, z: MyAvatar.position.z }, - localOnly: true, - volume: 0.2 - }); - lastBubbleSoundTimestamp = nowTimestamp; - } - hideOverlays(); - if (updateConnected === true) { - updateConnected = false; - Script.update.disconnect(update); - } - - Overlays.editOverlay(bubbleOverlay, { - dimensions: { - x: MyAvatar.sensorToWorldScale, - y: 0.75 * MyAvatar.sensorToWorldScale, - z: MyAvatar.sensorToWorldScale - }, - position: { - x: MyAvatar.position.x, - y: -MyAvatar.scale * 2 + MyAvatar.position.y + MyAvatar.scale * BUBBLE_HEIGHT_SCALE, - z: MyAvatar.position.z - }, - rotation: Quat.multiply(MyAvatar.orientation, Quat.fromVec3Degrees({x: 0.0, y: 180.0, z: 0.0})), - scale: { - x: 2 , - y: MyAvatar.scale * 0.5 + 0.5 , - z: 2 - }, - visible: true - }); - bubbleOverlayTimestamp = nowTimestamp; - Script.update.connect(update); - updateConnected = true; - } - - // Called from the C++ scripting interface to show the bubble overlay - function enteredIgnoreRadius() { - createOverlays(); - UserActivityLogger.privacyShieldActivated(); - } - - // Used to set the state of the bubble HUD button - function writeButtonProperties(parameter) { - button.editProperties({isActive: parameter}); - } - - // The bubble script's update function - function update() { - var timestamp = Date.now(); - var delay = (timestamp - bubbleOverlayTimestamp); - var overlayAlpha = 1.0 - (delay / BUBBLE_VISIBLE_DURATION_MS); - if (overlayAlpha > 0) { - if (delay < BUBBLE_RAISE_ANIMATION_DURATION_MS) { - Overlays.editOverlay(bubbleOverlay, { - dimensions: { - x: MyAvatar.sensorToWorldScale, - y: 0.75 * MyAvatar.sensorToWorldScale, - z: MyAvatar.sensorToWorldScale - }, - // Quickly raise the bubble from the ground up - position: { - x: MyAvatar.position.x, - y: (-((BUBBLE_RAISE_ANIMATION_DURATION_MS - delay) / BUBBLE_RAISE_ANIMATION_DURATION_MS)) * MyAvatar.scale * 2 + MyAvatar.position.y + MyAvatar.scale * BUBBLE_HEIGHT_SCALE, - z: MyAvatar.position.z - }, - rotation: Quat.multiply(MyAvatar.orientation, Quat.fromVec3Degrees({x: 0.0, y: 180.0, z: 0.0})), - scale: { - x: 2 , - y: ((1 - ((BUBBLE_RAISE_ANIMATION_DURATION_MS - delay) / BUBBLE_RAISE_ANIMATION_DURATION_MS)) * MyAvatar.scale * 0.5 + 0.5), - z: 2 - } - }); - } else { - // Keep the bubble in place for a couple seconds - Overlays.editOverlay(bubbleOverlay, { - dimensions: { - x: MyAvatar.sensorToWorldScale, - y: 0.75 * MyAvatar.sensorToWorldScale, - z: MyAvatar.sensorToWorldScale - }, - position: { - x: MyAvatar.position.x, - y: MyAvatar.position.y + MyAvatar.scale * BUBBLE_HEIGHT_SCALE, - z: MyAvatar.position.z - }, - rotation: Quat.multiply(MyAvatar.orientation, Quat.fromVec3Degrees({x: 0.0, y: 180.0, z: 0.0})), - scale: { - x: 2, - y: MyAvatar.scale * 0.5 + 0.5 , - z: 2 - } - }); - } - } else { - hideOverlays(); - if (updateConnected === true) { - Script.update.disconnect(update); - updateConnected = false; - } - } - } - - // When the space bubble is toggled... - // NOTE: the c++ calls this with just the first param -- we added a second - // just for not logging the initial state of the bubble when we startup. - function onBubbleToggled(enabled, doNotLog) { - writeButtonProperties(enabled); - if (doNotLog !== true) { - UserActivityLogger.privacyShieldToggled(enabled); - } - if (enabled) { - createOverlays(); - } else { - hideOverlays(); - if (updateConnected === true) { - Script.update.disconnect(update); - updateConnected = false; - } - } - } - - // Setup the bubble button - var buttonName = "SHIELD"; - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - button = tablet.addButton({ - icon: "icons/tablet-icons/bubble-i.svg", - activeIcon: "icons/tablet-icons/bubble-a.svg", - text: buttonName, - sortOrder: 4 - }); - - onBubbleToggled(Users.getIgnoreRadiusEnabled(), true); // pass in true so we don't log this initial one in the UserActivity table - - button.clicked.connect(Users.toggleIgnoreRadius); - Users.ignoreRadiusEnabledChanged.connect(onBubbleToggled); - Users.enteredIgnoreRadius.connect(enteredIgnoreRadius); - - // Cleanup the tablet button and overlays when script is stopped - Script.scriptEnding.connect(function () { - button.clicked.disconnect(Users.toggleIgnoreRadius); - if (tablet) { - tablet.removeButton(button); - } - Users.ignoreRadiusEnabledChanged.disconnect(onBubbleToggled); - Users.enteredIgnoreRadius.disconnect(enteredIgnoreRadius); - Overlays.deleteOverlay(bubbleOverlay); - if (updateConnected === true) { - Script.update.disconnect(update); - } - }); - -}()); // END LOCAL_SCOPE diff --git a/scripts/simplifiedUI/system/chat.js b/scripts/simplifiedUI/system/chat.js deleted file mode 100644 index 749665f3d8..0000000000 --- a/scripts/simplifiedUI/system/chat.js +++ /dev/null @@ -1,1010 +0,0 @@ -"use strict"; - -// Chat.js -// By Don Hopkins (dhopkins@donhopkins.com) -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -(function() { - - var webPageURL = Script.resolvePath("html/ChatPage.html"); // URL of tablet web page. - var randomizeWebPageURL = true; // Set to true for debugging. - var lastWebPageURL = ""; // Last random URL of tablet web page. - var onChatPage = false; // True when chat web page is opened. - var webHandlerConnected = false; // True when the web handler has been connected. - var channelName = "Chat"; // Unique name for channel that we listen to. - var tabletButtonName = "CHAT"; // Tablet button label. - var tabletButtonIcon = "icons/tablet-icons/menu-i.svg"; // Icon for chat button. - var tabletButtonActiveIcon = "icons/tablet-icons/menu-a.svg"; // Active icon for chat button. - var tabletButton = null; // The button we create in the tablet. - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); // The awesome tablet. - var chatLog = []; // Array of chat messages in the form of [avatarID, displayName, message, data]. - var avatarIdentifiers = {}; // Map of avatar ids to dict of identifierParams. - var speechBubbleShowing = false; // Is the speech bubble visible? - var speechBubbleMessage = null; // The message shown in the speech bubble. - var speechBubbleData = null; // The data of the speech bubble message. - var speechBubbleTextID = null; // The id of the speech bubble local text entity. - var speechBubbleTimer = null; // The timer to pop down the speech bubble. - var speechBubbleParams = null; // The params used to create or edit the speech bubble. - - // Persistent variables saved in the Settings. - var chatName = ''; // The user's name shown in chat. - var chatLogMaxSize = 100; // The maximum number of chat messages we remember. - var sendTyping = true; // Send typing begin and end notification. - var identifyAvatarDuration = 10; // How long to leave the avatar identity line up, in seconds. - var identifyAvatarLineColor = { red: 0, green: 255, blue: 0 }; // The color of the avatar identity line. - var identifyAvatarMyJointName = 'Head'; // My bone from which to draw the avatar identity line. - var identifyAvatarYourJointName = 'Head'; // Your bone to which to draw the avatar identity line. - var speechBubbleDuration = 10; // How long to leave the speech bubble up, in seconds. - var speechBubbleTextColor = {red: 255, green: 255, blue: 255}; // The text color of the speech bubble. - var speechBubbleBackgroundColor = {red: 0, green: 0, blue: 0}; // The background color of the speech bubble. - var speechBubbleOffset = {x: 0, y: 0.3, z: 0.0}; // The offset from the joint to whic the speech bubble is attached. - var speechBubbleJointName = 'Head'; // The name of the joint to which the speech bubble is attached. - var speechBubbleLineHeight = 0.05; // The height of a line of text in the speech bubble. - var SPEECH_BUBBLE_MAX_WIDTH = 1; // meters - - var textSizeOverlay = Overlays.addOverlay("text3d", { - position: MyAvatar.position, - lineHeight: speechBubbleLineHeight, - leftMargin: 0, - topMargin: 0, - rightMargin: 0, - bottomMargin: 0, - ignoreRayIntersection: true, - visible: false - }); - - // Load the persistent variables from the Settings, with defaults. - function loadSettings() { - chatName = Settings.getValue('Chat_chatName', MyAvatar.displayName); - if (!chatName) { - chatName = randomAvatarName(); - } - chatLogMaxSize = Settings.getValue('Chat_chatLogMaxSize', 100); - sendTyping = Settings.getValue('Chat_sendTyping', true); - identifyAvatarDuration = Settings.getValue('Chat_identifyAvatarDuration', 10); - identifyAvatarLineColor = Settings.getValue('Chat_identifyAvatarLineColor', { red: 0, green: 255, blue: 0 }); - identifyAvatarMyJointName = Settings.getValue('Chat_identifyAvatarMyJointName', 'Head'); - identifyAvatarYourJointName = Settings.getValue('Chat_identifyAvatarYourJointName', 'Head'); - speechBubbleDuration = Settings.getValue('Chat_speechBubbleDuration', 10); - speechBubbleTextColor = Settings.getValue('Chat_speechBubbleTextColor', {red: 255, green: 255, blue: 255}); - speechBubbleBackgroundColor = Settings.getValue('Chat_speechBubbleBackgroundColor', {red: 0, green: 0, blue: 0}); - speechBubbleOffset = Settings.getValue('Chat_speechBubbleOffset', {x: 0.0, y: 0.3, z:0.0}); - speechBubbleJointName = Settings.getValue('Chat_speechBubbleJointName', 'Head'); - speechBubbleLineHeight = Settings.getValue('Chat_speechBubbleLineHeight', 0.05); - Overlays.editOverlay(textSizeOverlay, { - lineHeight: speechBubbleLineHeight - }); - - saveSettings(); - } - - // Save the persistent variables to the Settings. - function saveSettings() { - Settings.setValue('Chat_chatName', chatName); - Settings.setValue('Chat_chatLogMaxSize', chatLogMaxSize); - Settings.setValue('Chat_sendTyping', sendTyping); - Settings.setValue('Chat_identifyAvatarDuration', identifyAvatarDuration); - Settings.setValue('Chat_identifyAvatarLineColor', identifyAvatarLineColor); - Settings.setValue('Chat_identifyAvatarMyJointName', identifyAvatarMyJointName); - Settings.setValue('Chat_identifyAvatarYourJointName', identifyAvatarYourJointName); - Settings.setValue('Chat_speechBubbleDuration', speechBubbleDuration); - Settings.setValue('Chat_speechBubbleTextColor', speechBubbleTextColor); - Settings.setValue('Chat_speechBubbleBackgroundColor', speechBubbleBackgroundColor); - Settings.setValue('Chat_speechBubbleOffset', speechBubbleOffset); - Settings.setValue('Chat_speechBubbleJointName', speechBubbleJointName); - Settings.setValue('Chat_speechBubbleLineHeight', speechBubbleLineHeight); - } - - // Reset the Settings and persistent variables to the defaults. - function resetSettings() { - Settings.setValue('Chat_chatName', null); - Settings.setValue('Chat_chatLogMaxSize', null); - Settings.setValue('Chat_sendTyping', null); - Settings.setValue('Chat_identifyAvatarDuration', null); - Settings.setValue('Chat_identifyAvatarLineColor', null); - Settings.setValue('Chat_identifyAvatarMyJointName', null); - Settings.setValue('Chat_identifyAvatarYourJointName', null); - Settings.setValue('Chat_speechBubbleDuration', null); - Settings.setValue('Chat_speechBubbleTextColor', null); - Settings.setValue('Chat_speechBubbleBackgroundColor', null); - Settings.setValue('Chat_speechBubbleOffset', null); - Settings.setValue('Chat_speechBubbleJointName', null); - Settings.setValue('Chat_speechBubbleLineHeight', null); - - loadSettings(); - } - - // Update anything that might depend on the settings. - function updateSettings() { - updateSpeechBubble(); - trimChatLog(); - updateChatPage(); - } - - // Trim the chat log so it is no longer than chatLogMaxSize lines. - function trimChatLog() { - if (chatLog.length > chatLogMaxSize) { - chatLog.splice(0, chatLogMaxSize - chatLog.length); - } - } - - // Clear the local chat log. - function clearChatLog() { - //print("clearChatLog"); - chatLog = []; - updateChatPage(); - } - - // We got a chat message from the channel. - // Trim the chat log, save the latest message in the chat log, - // and show the message on the tablet, if the chat page is showing. - function handleTransmitChatMessage(avatarID, displayName, message, data) { - //print("receiveChat", "avatarID", avatarID, "displayName", displayName, "message", message, "data", data); - - trimChatLog(); - chatLog.push([avatarID, displayName, message, data]); - - if (onChatPage) { - tablet.emitScriptEvent( - JSON.stringify({ - type: "ReceiveChatMessage", - avatarID: avatarID, - displayName: displayName, - message: message, - data: data - })); - } - } - - // Trim the chat log, save the latest log message in the chat log, - // and show the message on the tablet, if the chat page is showing. - function logMessage(message, data) { - //print("logMessage", message, data); - - trimChatLog(); - chatLog.push([null, null, message, data]); - - if (onChatPage) { - tablet.emitScriptEvent( - JSON.stringify({ - type: "LogMessage", - message: message, - data: data - })); - } - } - - // An empty chat message was entered. - // Hide our speech bubble. - function emptyChatMessage(data) { - popDownSpeechBubble(); - } - - // Notification that we typed a keystroke. - function type() { - //print("type"); - } - - // Notification that we began typing. - // Notify everyone that we started typing. - function beginTyping() { - //print("beginTyping"); - if (!sendTyping) { - return; - } - - Messages.sendMessage( - channelName, - JSON.stringify({ - type: 'AvatarBeginTyping', - avatarID: MyAvatar.sessionUUID, - displayName: chatName - })); - } - - // Notification that somebody started typing. - function handleAvatarBeginTyping(avatarID, displayName) { - //print("handleAvatarBeginTyping:", "avatarID", avatarID, displayName); - } - - // Notification that we stopped typing. - // Notify everyone that we stopped typing. - function endTyping() { - //print("endTyping"); - if (!sendTyping) { - return; - } - - Messages.sendMessage( - channelName, - JSON.stringify({ - type: 'AvatarEndTyping', - avatarID: MyAvatar.sessionUUID, - displayName: chatName - })); - } - - // Notification that somebody stopped typing. - function handleAvatarEndTyping(avatarID, displayName) { - //print("handleAvatarEndTyping:", "avatarID", avatarID, displayName); - } - - // Identify an avatar by drawing a line from our head to their head. - // If the avatar is our own, then just draw a line up into the sky. - function identifyAvatar(yourAvatarID) { - //print("identifyAvatar", yourAvatarID); - - unidentifyAvatars(); - - var myAvatarID = MyAvatar.sessionUUID; - var myJointIndex = MyAvatar.getJointIndex(identifyAvatarMyJointName); - var myJointRotation = - Quat.multiply( - MyAvatar.orientation, - MyAvatar.getAbsoluteJointRotationInObjectFrame(myJointIndex)); - var myJointPosition = - Vec3.sum( - MyAvatar.position, - Vec3.multiplyQbyV( - MyAvatar.orientation, - MyAvatar.getAbsoluteJointTranslationInObjectFrame(myJointIndex))); - - var yourJointIndex = -1; - var yourJointPosition; - - if (yourAvatarID == myAvatarID) { - - // You pointed at your own name, so draw a line up from your head. - - yourJointPosition = { - x: myJointPosition.x, - y: myJointPosition.y + 1000.0, - z: myJointPosition.z - }; - - } else { - - // You pointed at somebody else's name, so draw a line from your head to their head. - - var yourAvatar = AvatarList.getAvatar(yourAvatarID); - if (!yourAvatar) { - return; - } - - yourJointIndex = yourAvatar.getJointIndex(identifyAvatarMyJointName) - - var yourJointRotation = - Quat.multiply( - yourAvatar.orientation, - yourAvatar.getAbsoluteJointRotationInObjectFrame(yourJointIndex)); - yourJointPosition = - Vec3.sum( - yourAvatar.position, - Vec3.multiplyQbyV( - yourAvatar.orientation, - yourAvatar.getAbsoluteJointTranslationInObjectFrame(yourJointIndex))); - - } - - var identifierParams = { - parentID: myAvatarID, - parentJointIndex: myJointIndex, - lifetime: identifyAvatarDuration, - start: myJointPosition, - endParentID: yourAvatarID, - endParentJointIndex: yourJointIndex, - end: yourJointPosition, - color: identifyAvatarLineColor, - alpha: 1 - }; - - avatarIdentifiers[yourAvatarID] = identifierParams; - - identifierParams.lineID = Overlays.addOverlay("line3d", identifierParams); - - //print("ADDOVERLAY lineID", lineID, "myJointPosition", JSON.stringify(myJointPosition), "yourJointPosition", JSON.stringify(yourJointPosition), "lineData", JSON.stringify(lineData)); - - identifierParams.timer = - Script.setTimeout(function() { - //print("DELETEOVERLAY lineID"); - unidentifyAvatar(yourAvatarID); - }, identifyAvatarDuration * 1000); - - } - - // Stop identifying an avatar. - function unidentifyAvatar(yourAvatarID) { - //print("unidentifyAvatar", yourAvatarID); - - var identifierParams = avatarIdentifiers[yourAvatarID]; - if (!identifierParams) { - return; - } - - if (identifierParams.timer) { - Script.clearTimeout(identifierParams.timer); - } - - if (identifierParams.lineID) { - Overlays.deleteOverlay(identifierParams.lineID); - } - - delete avatarIdentifiers[yourAvatarID]; - } - - // Stop identifying all avatars. - function unidentifyAvatars() { - var ids = []; - - for (var avatarID in avatarIdentifiers) { - ids.push(avatarID); - } - - for (var i = 0, n = ids.length; i < n; i++) { - var avatarID = ids[i]; - unidentifyAvatar(avatarID); - } - - } - - // Turn to face another avatar. - function faceAvatar(yourAvatarID, displayName) { - //print("faceAvatar:", yourAvatarID, displayName); - - var myAvatarID = MyAvatar.sessionUUID; - if (yourAvatarID == myAvatarID) { - // You clicked on yourself. - return; - } - - var yourAvatar = AvatarList.getAvatar(yourAvatarID); - if (!yourAvatar) { - logMessage(displayName + ' is not here!', null); - return; - } - - // Project avatar positions to the floor and get the direction between those points, - // then face my avatar towards your avatar. - var yourPosition = yourAvatar.position; - yourPosition.y = 0; - var myPosition = MyAvatar.position; - myPosition.y = 0; - var myOrientation = Quat.lookAtSimple(myPosition, yourPosition); - MyAvatar.orientation = myOrientation; - } - - // Make a hopefully unique random anonymous avatar name. - function randomAvatarName() { - return 'Anon_' + Math.floor(Math.random() * 1000000); - } - - // Change the avatar size to bigger. - function biggerSize() { - //print("biggerSize"); - logMessage("Increasing avatar size", null); - MyAvatar.increaseSize(); - } - - // Change the avatar size to smaller. - function smallerSize() { - //print("smallerSize"); - logMessage("Decreasing avatar size", null); - MyAvatar.decreaseSize(); - } - - // Set the avatar size to normal. - function normalSize() { - //print("normalSize"); - logMessage("Resetting avatar size to normal!", null); - MyAvatar.resetSize(); - } - - // Send out a "Who" message, including our avatarID as myAvatarID, - // which will be sent in the response, so we can tell the reply - // is to our request. - function transmitWho() { - //print("transmitWho"); - logMessage("Who is here?", null); - Messages.sendMessage( - channelName, - JSON.stringify({ - type: 'Who', - myAvatarID: MyAvatar.sessionUUID - })); - } - - // Send a reply to a "Who" message, with a friendly message, - // our avatarID and our displayName. myAvatarID is the id - // of the avatar who send the Who message, to whom we're - // responding. - function handleWho(myAvatarID) { - var avatarID = MyAvatar.sessionUUID; - if (myAvatarID == avatarID) { - // Don't reply to myself. - return; - } - - var message = "I'm here!"; - var data = {}; - - Messages.sendMessage( - channelName, - JSON.stringify({ - type: 'ReplyWho', - myAvatarID: myAvatarID, - avatarID: avatarID, - displayName: chatName, - message: message, - data: data - })); - } - - // Receive the reply to a "Who" message. Ignore it unless we were the one - // who sent it out (if myAvatarIS is our avatar's id). - function handleReplyWho(myAvatarID, avatarID, displayName, message, data) { - if (myAvatarID != MyAvatar.sessionUUID) { - return; - } - - handleTransmitChatMessage(avatarID, displayName, message, data); - } - - // Handle input form the user, possibly multiple lines separated by newlines. - // Each line may be a chat command starting with "/", or a chat message. - function handleChatMessage(message, data) { - - var messageLines = message.trim().split('\n'); - - for (var i = 0, n = messageLines.length; i < n; i++) { - var messageLine = messageLines[i]; - - if (messageLine.substr(0, 1) == '/') { - handleChatCommand(messageLine, data); - } else { - transmitChatMessage(messageLine, data); - } - } - - } - - // Handle a chat command prefixed by "/". - function handleChatCommand(message, data) { - - var commandLine = message.substr(1); - var tokens = commandLine.trim().split(' '); - var command = tokens[0]; - var rest = commandLine.substr(command.length + 1).trim(); - - //print("commandLine", commandLine, "command", command, "tokens", tokens, "rest", rest); - - switch (command) { - - case '?': - case 'help': - logMessage('Type "/?" or "/help" for help', null); - logMessage('Type "/name " to set your chat name, or "/name" to use your display name. If your display name is not defined, a random name will be used.', null); - logMessage('Type "/close" to close your overhead chat message.', null); - logMessage('Type "/say " to display a new message.', null); - logMessage('Type "/clear" to clear your chat log.', null); - logMessage('Type "/who" to ask who is in the chat session.', null); - logMessage('Type "/bigger", "/smaller" or "/normal" to change your avatar size.', null); - break; - - case 'name': - if (rest == '') { - if (MyAvatar.displayName) { - chatName = MyAvatar.displayName; - saveSettings(); - logMessage('Your chat name has been set to your display name "' + chatName + '".', null); - } else { - chatName = randomAvatarName(); - saveSettings(); - logMessage('Your avatar\'s display name is not defined, so your chat name has been set to "' + chatName + '".', null); - } - } else { - chatName = rest; - saveSettings(); - logMessage('Your chat name has been set to "' + chatName + '".', null); - } - break; - - case 'close': - popDownSpeechBubble(); - logMessage('Overhead chat message closed.', null); - break; - - case 'say': - if (rest == '') { - emptyChatMessage(data); - } else { - transmitChatMessage(rest, data); - } - break; - - case 'who': - transmitWho(); - break; - - case 'clear': - clearChatLog(); - break; - - case 'bigger': - biggerSize(); - break; - - case 'smaller': - smallerSize(); - break; - - case 'normal': - normalSize(); - break; - - case 'resetsettings': - resetSettings(); - updateSettings(); - break; - - case 'speechbubbleheight': - var y = parseInt(rest); - if (!isNaN(y)) { - speechBubbleOffset.y = y; - } - saveSettings(); - updateSettings(); - break; - - case 'speechbubbleduration': - var duration = parseFloat(rest); - if (!isNaN(duration)) { - speechBubbleDuration = duration; - } - saveSettings(); - updateSettings(); - break; - - default: - logMessage('Unknown chat command. Type "/help" or "/?" for help.', null); - break; - - } - - } - - // Send out a chat message to everyone. - function transmitChatMessage(message, data) { - //print("transmitChatMessage", 'avatarID', avatarID, 'displayName', displayName, 'message', message, 'data', data); - - popUpSpeechBubble(message, data); - - Messages.sendMessage( - channelName, - JSON.stringify({ - type: 'TransmitChatMessage', - avatarID: MyAvatar.sessionUUID, - displayName: chatName, - message: message, - data: data - })); - - } - - // Show the speech bubble. - function popUpSpeechBubble(message, data) { - //print("popUpSpeechBubble", message, data); - - popDownSpeechBubble(); - - speechBubbleShowing = true; - speechBubbleMessage = message; - speechBubbleData = data; - - updateSpeechBubble(); - - if (speechBubbleDuration > 0) { - speechBubbleTimer = Script.setTimeout( - function () { - popDownSpeechBubble(); - }, - speechBubbleDuration * 1000); - } - } - - // Update the speech bubble. - // This is factored out so we can update an existing speech bubble if any settings change. - function updateSpeechBubble() { - if (!speechBubbleShowing) { - return; - } - - var jointIndex = MyAvatar.getJointIndex(speechBubbleJointName); - var dimensions = { - x: 100.0, - y: 100.0, - z: 0.1 - }; - - speechBubbleParams = { - type: "Text", - lifetime: speechBubbleDuration, - parentID: MyAvatar.sessionUUID, - jointIndex: jointIndex, - dimensions: dimensions, - lineHeight: speechBubbleLineHeight, - leftMargin: 0, - topMargin: 0, - rightMargin: 0, - bottomMargin: 0, - faceCamera: true, - drawInFront: true, - ignoreRayIntersection: true, - text: speechBubbleMessage, - textColor: speechBubbleTextColor, - color: speechBubbleTextColor, - backgroundColor: speechBubbleBackgroundColor - }; - - // Only overlay text3d has a way to measure the text, not entities. - // So we make a temporary one just for measuring text, then delete it. - var speechBubbleTextOverlayID = Overlays.addOverlay("text3d", speechBubbleParams); - var textSize = Overlays.textSize(textSizeOverlay, speechBubbleMessage); - try { - Overlays.deleteOverlay(speechBubbleTextOverlayID); - } catch (e) {} - - //print("updateSpeechBubble:", "speechBubbleMessage", speechBubbleMessage, "textSize", textSize.width, textSize.height); - - var fudge = 0.02; - - var width = textSize.width + fudge; - var height = speechBubbleLineHeight + fudge; - - if (textSize.width >= SPEECH_BUBBLE_MAX_WIDTH) { - var numLines = Math.ceil(width); - height = speechBubbleLineHeight * numLines + fudge; - width = SPEECH_BUBBLE_MAX_WIDTH; - } - - dimensions = { - x: width, - y: height, - z: 0.1 - }; - speechBubbleParams.dimensions = dimensions; - - var headRotation = - Quat.multiply( - MyAvatar.orientation, - MyAvatar.getAbsoluteJointRotationInObjectFrame(jointIndex)); - var headPosition = - Vec3.sum( - MyAvatar.position, - Vec3.multiplyQbyV( - MyAvatar.orientation, - MyAvatar.getAbsoluteJointTranslationInObjectFrame(jointIndex))); - var rotatedOffset = - Vec3.multiplyQbyV( - headRotation, - speechBubbleOffset); - var position = - Vec3.sum( - headPosition, - rotatedOffset); - position.y += height / 2; // offset based on half of bubble height - speechBubbleParams.position = position; - - if (!speechBubbleTextID) { - speechBubbleTextID = - Entities.addEntity(speechBubbleParams, true); - } else { - Entities.editEntity(speechBubbleTextID, speechBubbleParams); - } - - //print("speechBubbleTextID:", speechBubbleTextID, "speechBubbleParams", JSON.stringify(speechBubbleParams)); - } - - // Hide the speech bubble. - function popDownSpeechBubble() { - cancelSpeechBubbleTimer(); - - speechBubbleShowing = false; - - //print("popDownSpeechBubble speechBubbleTextID", speechBubbleTextID); - - if (speechBubbleTextID) { - try { - Entities.deleteEntity(speechBubbleTextID); - } catch (e) {} - speechBubbleTextID = null; - } - } - - // Cancel the speech bubble popup timer. - function cancelSpeechBubbleTimer() { - if (speechBubbleTimer) { - Script.clearTimeout(speechBubbleTimer); - speechBubbleTimer = null; - } - } - - // Show the tablet web page and connect the web handler. - function showTabletWebPage() { - var url = Script.resolvePath(webPageURL); - if (randomizeWebPageURL) { - url += '?rand=' + Math.random(); - } - lastWebPageURL = url; - onChatPage = true; - tablet.gotoWebScreen(lastWebPageURL); - // Connect immediately so we don't miss anything. - connectWebHandler(); - } - - // Update the tablet web page with the chat log. - function updateChatPage() { - if (!onChatPage) { - return; - } - - tablet.emitScriptEvent( - JSON.stringify({ - type: "Update", - chatLog: chatLog - })); - } - - function onChatMessageReceived(channel, message, senderID) { - - // Ignore messages to any other channel than mine. - if (channel != channelName) { - return; - } - - // Parse the message and pull out the message parameters. - var messageData = JSON.parse(message); - var messageType = messageData.type; - - //print("MESSAGE", message); - //print("MESSAGEDATA", messageData, JSON.stringify(messageData)); - - switch (messageType) { - - case 'TransmitChatMessage': - handleTransmitChatMessage(messageData.avatarID, messageData.displayName, messageData.message, messageData.data); - break; - - case 'AvatarBeginTyping': - handleAvatarBeginTyping(messageData.avatarID, messageData.displayName); - break; - - case 'AvatarEndTyping': - handleAvatarEndTyping(messageData.avatarID, messageData.displayName); - break; - - case 'Who': - handleWho(messageData.myAvatarID); - break; - - case 'ReplyWho': - handleReplyWho(messageData.myAvatarID, messageData.avatarID, messageData.displayName, messageData.message, messageData.data); - break; - - default: - print("onChatMessageReceived: unknown messageType", messageType, "message", message); - break; - - } - - } - - // Handle events from the tablet web page. - function onWebEventReceived(event) { - if (!onChatPage) { - return; - } - - //print("onWebEventReceived: event", event); - - var eventData = JSON.parse(event); - var eventType = eventData.type; - - switch (eventType) { - - case 'Ready': - updateChatPage(); - break; - - case 'Update': - updateChatPage(); - break; - - case 'HandleChatMessage': - var message = eventData.message; - var data = eventData.data; - //print("onWebEventReceived: HandleChatMessage:", 'message', message, 'data', data); - handleChatMessage(message, data); - break; - - case 'PopDownSpeechBubble': - popDownSpeechBubble(); - break; - - case 'EmptyChatMessage': - emptyChatMessage(); - break; - - case 'Type': - type(); - break; - - case 'BeginTyping': - beginTyping(); - break; - - case 'EndTyping': - endTyping(); - break; - - case 'IdentifyAvatar': - identifyAvatar(eventData.avatarID); - break; - - case 'UnidentifyAvatar': - unidentifyAvatar(eventData.avatarID); - break; - - case 'FaceAvatar': - faceAvatar(eventData.avatarID, eventData.displayName); - break; - - case 'ClearChatLog': - clearChatLog(); - break; - - case 'Who': - transmitWho(); - break; - - case 'Bigger': - biggerSize(); - break; - - case 'Smaller': - smallerSize(); - break; - - case 'Normal': - normalSize(); - break; - - default: - print("onWebEventReceived: unexpected eventType", eventType); - break; - - } - } - - function onScreenChanged(type, url) { - //print("onScreenChanged", "type", type, "url", url, "lastWebPageURL", lastWebPageURL); - - if ((type === "Web") && - (url === lastWebPageURL)) { - if (!onChatPage) { - onChatPage = true; - connectWebHandler(); - } - } else { - if (onChatPage) { - onChatPage = false; - disconnectWebHandler(); - } - } - - } - - function connectWebHandler() { - if (webHandlerConnected) { - return; - } - - try { - tablet.webEventReceived.connect(onWebEventReceived); - } catch (e) { - print("connectWebHandler: error connecting: " + e); - return; - } - - webHandlerConnected = true; - //print("connectWebHandler connected"); - - updateChatPage(); - } - - function disconnectWebHandler() { - if (!webHandlerConnected) { - return; - } - - try { - tablet.webEventReceived.disconnect(onWebEventReceived); - } catch (e) { - print("disconnectWebHandler: error disconnecting web handler: " + e); - return; - } - webHandlerConnected = false; - - //print("disconnectWebHandler: disconnected"); - } - - // Show the tablet web page when the chat button on the tablet is clicked. - function onTabletButtonClicked() { - showTabletWebPage(); - } - - // Shut down the chat application when the tablet button is destroyed. - function onTabletButtonDestroyed() { - shutDown(); - } - - // Start up the chat application. - function startUp() { - //print("startUp"); - - loadSettings(); - - tabletButton = tablet.addButton({ - icon: tabletButtonIcon, - activeIcon: tabletButtonActiveIcon, - text: tabletButtonName - }); - - Messages.subscribe(channelName); - - tablet.screenChanged.connect(onScreenChanged); - - Messages.messageReceived.connect(onChatMessageReceived); - - tabletButton.clicked.connect(onTabletButtonClicked); - - Script.scriptEnding.connect(onTabletButtonDestroyed); - - logMessage('Type "/?" or "/help" for help with chat.', null); - - //print("Added chat button to tablet."); - } - - // Shut down the chat application. - function shutDown() { - //print("shutDown"); - - popDownSpeechBubble(); - unidentifyAvatars(); - disconnectWebHandler(); - - Overlays.deleteOverlay(textSizeOverlay); - - if (onChatPage) { - tablet.gotoHomeScreen(); - onChatPage = false; - } - - tablet.screenChanged.disconnect(onScreenChanged); - - Messages.messageReceived.disconnect(onChatMessageReceived); - - // Clean up the tablet button we made. - tabletButton.clicked.disconnect(onTabletButtonClicked); - tablet.removeButton(tabletButton); - tabletButton = null; - - //print("Removed chat button from tablet."); - } - - // Kick off the chat application! - startUp(); - -}()); diff --git a/scripts/simplifiedUI/system/clickToAvatarApp.js b/scripts/simplifiedUI/system/clickToAvatarApp.js deleted file mode 100644 index 8024f595b5..0000000000 --- a/scripts/simplifiedUI/system/clickToAvatarApp.js +++ /dev/null @@ -1,7 +0,0 @@ -(function () { - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - this.clickDownOnEntity = function (entityID, mouseEvent) { - tablet.loadQMLSource("hifi/AvatarApp.qml"); - }; -} -); diff --git a/scripts/simplifiedUI/system/commerce/wallet.js b/scripts/simplifiedUI/system/commerce/wallet.js deleted file mode 100644 index 86806fd8b4..0000000000 --- a/scripts/simplifiedUI/system/commerce/wallet.js +++ /dev/null @@ -1,737 +0,0 @@ -"use strict"; -/* jslint vars:true, plusplus:true, forin:true */ -/* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ -// -// wallet.js -// -// Created by Zach Fox on 2017-08-17 -// 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 -// - -/* global getConnectionData getControllerWorldLocation openLoginWindow WalletScriptingInterface */ - -(function () { // BEGIN LOCAL_SCOPE -Script.include("/~/system/libraries/accountUtils.js"); -Script.include("/~/system/libraries/connectionUtils.js"); -var AppUi = Script.require('appUi'); - -var MARKETPLACE_URL = Account.metaverseServerURL + "/marketplace"; - -// BEGIN AVATAR SELECTOR LOGIC -var UNSELECTED_COLOR = { red: 0x1F, green: 0xC6, blue: 0xA6 }; -var SELECTED_COLOR = { red: 0xF3, green: 0x91, blue: 0x29 }; -var HOVER_COLOR = { red: 0xD0, green: 0xD0, blue: 0xD0 }; - -var overlays = {}; // Keeps track of all our extended overlay data objects, keyed by target identifier. - -function ExtendedOverlay(key, type, properties) { // A wrapper around overlays to store the key it is associated with. - overlays[key] = this; - this.key = key; - this.selected = false; - this.hovering = false; - this.activeOverlay = Overlays.addOverlay(type, properties); // We could use different overlays for (un)selected... -} -// Instance methods: -ExtendedOverlay.prototype.deleteOverlay = function () { // remove display and data of this overlay - Overlays.deleteOverlay(this.activeOverlay); - delete overlays[this.key]; -}; - -ExtendedOverlay.prototype.editOverlay = function (properties) { // change display of this overlay - Overlays.editOverlay(this.activeOverlay, properties); -}; - -function color(selected, hovering) { - var base = hovering ? HOVER_COLOR : selected ? SELECTED_COLOR : UNSELECTED_COLOR; - function scale(component) { - return component; - } - return { red: scale(base.red), green: scale(base.green), blue: scale(base.blue) }; -} -// so we don't have to traverse the overlays to get the last one -var lastHoveringId = 0; -ExtendedOverlay.prototype.hover = function (hovering) { - this.hovering = hovering; - if (this.key === lastHoveringId) { - if (hovering) { - return; - } - lastHoveringId = 0; - } - this.editOverlay({ color: color(this.selected, hovering) }); - if (hovering) { - // un-hover the last hovering overlay - if (lastHoveringId && lastHoveringId !== this.key) { - ExtendedOverlay.get(lastHoveringId).hover(false); - } - lastHoveringId = this.key; - } -}; -ExtendedOverlay.prototype.select = function (selected) { - if (this.selected === selected) { - return; - } - - this.editOverlay({ color: color(selected, this.hovering) }); - this.selected = selected; -}; -// Class methods: -var selectedId = false; -ExtendedOverlay.isSelected = function (id) { - return selectedId === id; -}; -ExtendedOverlay.get = function (key) { // answer the extended overlay data object associated with the given avatar identifier - return overlays[key]; -}; -ExtendedOverlay.some = function (iterator) { // Bails early as soon as iterator returns truthy. - var key; - for (key in overlays) { - if (iterator(ExtendedOverlay.get(key))) { - return; - } - } -}; -ExtendedOverlay.unHover = function () { // calls hover(false) on lastHoveringId (if any) - if (lastHoveringId) { - ExtendedOverlay.get(lastHoveringId).hover(false); - } -}; - -// hit(overlay) on the one overlay intersected by pickRay, if any. -// noHit() if no ExtendedOverlay was intersected (helps with hover) -ExtendedOverlay.applyPickRay = function (pickRay, hit, noHit) { - // Depends on nearer coverOverlays to extend closer to us than farther ones. - var pickedOverlay = Overlays.findRayIntersection(pickRay); - if (!pickedOverlay.intersects) { - if (noHit) { - return noHit(); - } - return; - } - ExtendedOverlay.some(function (overlay) { // See if pickedOverlay is one of ours. - if ((overlay.activeOverlay) === pickedOverlay.overlayID) { - hit(overlay); - return true; - } - }); -}; - -function addAvatarNode(id) { - return new ExtendedOverlay(id, "sphere", { - drawInFront: true, - solid: true, - alpha: 0.8, - color: color(false, false), - ignoreRayIntersection: false - }); -} - -var pingPong = true; -var OVERLAY_SCALE = 0.032; -function updateOverlays() { - var eye = Camera.position; - AvatarList.getAvatarIdentifiers().forEach(function (id) { - if (!id) { - return; // don't update ourself, or avatars we're not interested in - } - var avatar = AvatarList.getAvatar(id); - if (!avatar) { - return; // will be deleted below if there had been an overlay. - } - var overlay = ExtendedOverlay.get(id); - if (!overlay) { // For now, we're treating this as a temporary loss, as from the personal space bubble. Add it back. - overlay = addAvatarNode(id); - } - var target = avatar.position; - var distance = Vec3.distance(target, eye); - var offset = 0.2; - // get diff between target and eye (a vector pointing to the eye from avatar position) - var diff = Vec3.subtract(target, eye); - var headIndex = avatar.getJointIndex("Head"); // base offset on 1/2 distance from hips to head if we can - if (headIndex > 0) { - offset = avatar.getAbsoluteJointTranslationInObjectFrame(headIndex).y / 2; - } - - // move a bit in front, towards the camera - target = Vec3.subtract(target, Vec3.multiply(Vec3.normalize(diff), offset)); - - // now bump it up a bit - target.y = target.y + offset; - - overlay.ping = pingPong; - overlay.editOverlay({ - color: color(ExtendedOverlay.isSelected(id), overlay.hovering), - position: target, - dimensions: OVERLAY_SCALE * distance - }); - }); - pingPong = !pingPong; - ExtendedOverlay.some(function (overlay) { // Remove any that weren't updated. (User is gone.) - if (overlay.ping === pingPong) { - overlay.deleteOverlay(); - } - }); -} -function removeOverlays() { - selectedId = false; - lastHoveringId = 0; - ExtendedOverlay.some(function (overlay) { - overlay.deleteOverlay(); - }); -} - -// -// Clicks. -// -function usernameFromIDReply(id, username, machineFingerprint, isAdmin) { - if (selectedId === id) { - var message = { - method: 'updateSelectedRecipientUsername', - userName: username === "" ? "unknown username" : username - }; - ui.sendMessage(message); - } -} -function handleClick(pickRay) { - ExtendedOverlay.applyPickRay(pickRay, function (overlay) { - var nextSelectedStatus = !overlay.selected; - var avatarId = overlay.key; - selectedId = nextSelectedStatus ? avatarId : false; - if (nextSelectedStatus) { - Users.requestUsernameFromID(avatarId); - } - var message = { - method: 'selectRecipient', - id: avatarId, - isSelected: nextSelectedStatus, - displayName: '"' + AvatarList.getAvatar(avatarId).sessionDisplayName + '"', - userName: '' - }; - ui.sendMessage(message); - - ExtendedOverlay.some(function (overlay) { - var id = overlay.key; - var selected = ExtendedOverlay.isSelected(id); - overlay.select(selected); - }); - - return true; - }); -} -function handleMouseEvent(mousePressEvent) { // handleClick if we get one. - if (!mousePressEvent.isLeftButton) { - return; - } - handleClick(Camera.computePickRay(mousePressEvent.x, mousePressEvent.y)); -} -function handleMouseMove(pickRay) { // given the pickRay, just do the hover logic - ExtendedOverlay.applyPickRay(pickRay, function (overlay) { - overlay.hover(true); - }, function () { - ExtendedOverlay.unHover(); - }); -} - -// handy global to keep track of which hand is the mouse (if any) -var currentHandPressed = 0; -var TRIGGER_CLICK_THRESHOLD = 0.85; -var TRIGGER_PRESS_THRESHOLD = 0.05; - -function handleMouseMoveEvent(event) { // find out which overlay (if any) is over the mouse position - var pickRay; - if (HMD.active) { - if (currentHandPressed !== 0) { - pickRay = controllerComputePickRay(currentHandPressed); - } else { - // nothing should hover, so - ExtendedOverlay.unHover(); - return; - } - } else { - pickRay = Camera.computePickRay(event.x, event.y); - } - handleMouseMove(pickRay); -} -function handleTriggerPressed(hand, value) { - // The idea is if you press one trigger, it is the one - // we will consider the mouse. Even if the other is pressed, - // we ignore it until this one is no longer pressed. - var isPressed = value > TRIGGER_PRESS_THRESHOLD; - if (currentHandPressed === 0) { - currentHandPressed = isPressed ? hand : 0; - return; - } - if (currentHandPressed === hand) { - currentHandPressed = isPressed ? hand : 0; - return; - } - // otherwise, the other hand is still triggered - // so do nothing. -} - -// We get mouseMoveEvents from the handControllers, via handControllerPointer. -// But we don't get mousePressEvents. -var triggerMapping = Controller.newMapping(Script.resolvePath('') + '-click'); -var triggerPressMapping = Controller.newMapping(Script.resolvePath('') + '-press'); -function controllerComputePickRay(hand) { - var controllerPose = getControllerWorldLocation(hand, true); - if (controllerPose.valid) { - return { origin: controllerPose.position, direction: Quat.getUp(controllerPose.orientation) }; - } -} -function makeClickHandler(hand) { - return function (clicked) { - if (clicked > TRIGGER_CLICK_THRESHOLD) { - var pickRay = controllerComputePickRay(hand); - handleClick(pickRay); - } - }; -} -function makePressHandler(hand) { - return function (value) { - handleTriggerPressed(hand, value); - }; -} -triggerMapping.from(Controller.Standard.RTClick).peek().to(makeClickHandler(Controller.Standard.RightHand)); -triggerMapping.from(Controller.Standard.LTClick).peek().to(makeClickHandler(Controller.Standard.LeftHand)); -triggerPressMapping.from(Controller.Standard.RT).peek().to(makePressHandler(Controller.Standard.RightHand)); -triggerPressMapping.from(Controller.Standard.LT).peek().to(makePressHandler(Controller.Standard.LeftHand)); -// END AVATAR SELECTOR LOGIC - -var sendMoneyRecipient; -var sendMoneyParticleEffectUpdateTimer; -var particleEffectTimestamp; -var sendMoneyParticleEffect; -var SEND_MONEY_PARTICLE_TIMER_UPDATE = 250; -var SEND_MONEY_PARTICLE_EMITTING_DURATION = 3000; -var SEND_MONEY_PARTICLE_LIFETIME_SECONDS = 8; -var SEND_MONEY_PARTICLE_PROPERTIES = { - accelerationSpread: { x: 0, y: 0, z: 0 }, - alpha: 1, - alphaFinish: 1, - alphaSpread: 0, - alphaStart: 1, - azimuthFinish: 0, - azimuthStart: -6, - color: { red: 143, green: 5, blue: 255 }, - colorFinish: { red: 255, green: 0, blue: 204 }, - colorSpread: { red: 0, green: 0, blue: 0 }, - colorStart: { red: 0, green: 136, blue: 255 }, - emitAcceleration: { x: 0, y: 0, z: 0 }, // Immediately gets updated to be accurate - emitDimensions: { x: 0, y: 0, z: 0 }, - emitOrientation: { x: 0, y: 0, z: 0 }, - emitRate: 4, - emitSpeed: 2.1, - emitterShouldTrail: true, - isEmitting: 1, - lifespan: SEND_MONEY_PARTICLE_LIFETIME_SECONDS + 1, // Immediately gets updated to be accurate - lifetime: SEND_MONEY_PARTICLE_LIFETIME_SECONDS + 1, - maxParticles: 20, - name: 'hfc-particles', - particleRadius: 0.2, - polarFinish: 0, - polarStart: 0, - radiusFinish: 0.05, - radiusSpread: 0, - radiusStart: 0.2, - speedSpread: 0, - textures: "http://hifi-content.s3.amazonaws.com/alan/dev/Particles/Bokeh-Particle-HFC.png", - type: 'ParticleEffect' -}; - -var MS_PER_SEC = 1000; -function updateSendMoneyParticleEffect() { - var timestampNow = Date.now(); - if ((timestampNow - particleEffectTimestamp) > (SEND_MONEY_PARTICLE_LIFETIME_SECONDS * MS_PER_SEC)) { - deleteSendMoneyParticleEffect(); - return; - } else if ((timestampNow - particleEffectTimestamp) > SEND_MONEY_PARTICLE_EMITTING_DURATION) { - Entities.editEntity(sendMoneyParticleEffect, { - isEmitting: 0 - }); - } else if (sendMoneyParticleEffect) { - var recipientPosition = AvatarList.getAvatar(sendMoneyRecipient).position; - var distance = Vec3.distance(recipientPosition, MyAvatar.position); - var accel = Vec3.subtract(recipientPosition, MyAvatar.position); - accel.y -= 3.0; - var life = Math.sqrt(2 * distance / Vec3.length(accel)); - Entities.editEntity(sendMoneyParticleEffect, { - emitAcceleration: accel, - lifespan: life - }); - } -} - -function deleteSendMoneyParticleEffect() { - if (sendMoneyParticleEffectUpdateTimer) { - Script.clearInterval(sendMoneyParticleEffectUpdateTimer); - sendMoneyParticleEffectUpdateTimer = null; - } - if (sendMoneyParticleEffect) { - sendMoneyParticleEffect = Entities.deleteEntity(sendMoneyParticleEffect); - } - sendMoneyRecipient = null; -} - -function onUsernameChanged() { - if (ui.checkIsOpen()) { - ui.open(WALLET_QML_SOURCE); - } -} - -var MARKETPLACE_QML_PATH = "hifi/commerce/marketplace/Marketplace.qml"; -function openMarketplace(optionalItem) { - ui.open(MARKETPLACE_QML_PATH); - - if (optionalItem) { - ui.tablet.sendToQml({ - method: 'updateMarketplaceQMLItem', - params: { itemId: optionalItem } - }); - } -} - -function setCertificateInfo(itemCertificateId) { - ui.tablet.sendToQml({ - method: 'inspectionCertificate_setCertificateId', - entityId: "", - certificateId: itemCertificateId - }); -} - -// Function Name: fromQml() -// -// Description: -// -Called when a message is received from SpectatorCamera.qml. The "message" argument is what is sent from the QML -// in the format "{method, params}", like json-rpc. See also sendToQml(). -function fromQml(message) { - switch (message.method) { - case 'passphrasePopup_cancelClicked': - case 'needsLogIn_cancelClicked': - ui.close(); - break; - case 'walletSetup_cancelClicked': - switch (message.referrer) { - case '': // User clicked "Wallet" app - case undefined: - case null: - ui.close(); - break; - case 'purchases': - case 'marketplace cta': - case 'mainPage': - openMarketplace(); - break; - default: - openMarketplace(); - break; - } - break; - case 'needsLogIn_loginClicked': - openLoginWindow(); - break; - case 'disableHmdPreview': - break; // do nothing here, handled in marketplaces.js - case 'maybeEnableHmdPreview': - break; // do nothing here, handled in marketplaces.js - case 'transactionHistory_linkClicked': - openMarketplace(message.itemId); - break; - case 'goToMarketplaceMainPage': - openMarketplace(); - break; - case 'goToMarketplaceItemPage': - openMarketplace(message.itemId); - break; - case 'refreshConnections': - print('Refreshing Connections...'); - getConnectionData(false); - break; - case 'enable_ChooseRecipientNearbyMode': - if (!isUpdateOverlaysWired) { - Script.update.connect(updateOverlays); - isUpdateOverlaysWired = true; - } - break; - case 'disable_ChooseRecipientNearbyMode': - if (isUpdateOverlaysWired) { - Script.update.disconnect(updateOverlays); - isUpdateOverlaysWired = false; - } - removeOverlays(); - break; - case 'sendAsset_sendPublicly': - deleteSendMoneyParticleEffect(); - sendMoneyRecipient = message.recipient; - var props = SEND_MONEY_PARTICLE_PROPERTIES; - props.parentID = MyAvatar.sessionUUID; - props.position = MyAvatar.position; - props.position.y += 0.2; - if (message.effectImage) { - props.textures = message.effectImage; - } - sendMoneyParticleEffect = Entities.addEntity(props, true); - particleEffectTimestamp = Date.now(); - updateSendMoneyParticleEffect(); - sendMoneyParticleEffectUpdateTimer = - Script.setInterval(updateSendMoneyParticleEffect, SEND_MONEY_PARTICLE_TIMER_UPDATE); - break; - case 'transactionHistory_goToBank': - if (Account.metaverseServerURL.indexOf("staging") >= 0) { - Window.location = "hifi://hifiqa-master-metaverse-staging"; // So that we can test in staging. - } else { - Window.location = "hifi://BankOfHighFidelity"; - } - break; - case 'purchases_updateWearables': - var currentlyWornWearables = []; - var ATTACHMENT_SEARCH_RADIUS = 100; // meters (just in case) - - var nearbyEntities = Entities.findEntitiesByType('Model', MyAvatar.position, ATTACHMENT_SEARCH_RADIUS); - - for (var i = 0; i < nearbyEntities.length; i++) { - var currentProperties = Entities.getEntityProperties( - nearbyEntities[i], ['certificateID', 'editionNumber', 'parentID'] - ); - if (currentProperties.parentID === MyAvatar.sessionUUID) { - currentlyWornWearables.push({ - entityID: nearbyEntities[i], - entityCertID: currentProperties.certificateID, - entityEdition: currentProperties.editionNumber - }); - } - } - - ui.tablet.sendToQml({ method: 'updateWearables', wornWearables: currentlyWornWearables }); - break; - case 'purchases_walletNotSetUp': - ui.tablet.sendToQml({ - method: 'updateWalletReferrer', - referrer: "purchases" - }); - break; - case 'purchases_openGoTo': - ui.open("hifi/tablet/TabletAddressDialog.qml"); - break; - case 'purchases_itemInfoClicked': - var itemId = message.itemId; - if (itemId && itemId !== "") { - openMarketplace(itemId); - } - break; - case 'purchases_itemCertificateClicked': - setCertificateInfo(message.itemCertificateId); - break; - case 'clearShouldShowDotHistory': - shouldShowDotHistory = false; - ui.messagesWaiting(shouldShowDotUpdates || shouldShowDotHistory); - break; - case 'clearShouldShowDotUpdates': - shouldShowDotUpdates = false; - ui.messagesWaiting(shouldShowDotUpdates || shouldShowDotHistory); - break; - case 'http.request': - // Handled elsewhere, don't log. - break; - case 'closeSendAsset': - ui.close(); - break; - default: - print('wallet.js: Unrecognized message from QML'); - } -} - -var isWired = false; -function walletOpened() { - Users.usernameFromIDReply.connect(usernameFromIDReply); - Controller.mousePressEvent.connect(handleMouseEvent); - Controller.mouseMoveEvent.connect(handleMouseMoveEvent); - triggerMapping.enable(); - triggerPressMapping.enable(); - isWired = true; - - if (shouldShowDotHistory) { - ui.sendMessage({ - method: 'updateRecentActivityMessageLight', - messagesWaiting: shouldShowDotHistory - }); - } -} - -function walletClosed() { - off(); -} - -function notificationDataProcessPageUpdates(data) { - return data.data.updates; -} - -function notificationDataProcessPageHistory(data) { - return data.data.history; -} - -var shouldShowDotUpdates = false; -function notificationPollCallbackUpdates(updatesArray) { - shouldShowDotUpdates = updatesArray.length > 0; - ui.messagesWaiting(shouldShowDotUpdates || shouldShowDotHistory); - - if (updatesArray.length > 0) { - var message; - if (!ui.notificationInitialCallbackMade[0]) { - message = updatesArray.length + " of your purchased items " + - (updatesArray.length === 1 ? "has an update " : "have updates ") + - "available. Open INVENTORY to update."; - ui.notificationDisplayBanner(message); - - ui.notificationPollCaresAboutSince[0] = true; - } else { - for (var i = 0; i < updatesArray.length; i++) { - message = "Update available for \"" + - updatesArray[i].base_item_title + "\"." + - "Open INVENTORY to update."; - ui.notificationDisplayBanner(message); - } - } - } -} -var shouldShowDotHistory = false; -function notificationPollCallbackHistory(historyArray) { - if (!ui.isOpen) { - var notificationCount = historyArray.length; - shouldShowDotHistory = shouldShowDotHistory || notificationCount > 0; - ui.messagesWaiting(shouldShowDotUpdates || shouldShowDotHistory); - - if (notificationCount > 0) { - var message; - if (!ui.notificationInitialCallbackMade[1]) { - message = "You have " + notificationCount + " unread recent " + - "transaction" + (notificationCount === 1 ? "" : "s") + ". Open INVENTORY to see all activity."; - ui.notificationDisplayBanner(message); - } else { - for (var i = 0; i < notificationCount; i++) { - var historyMessage = historyArray[i].message; - var sanitizedHistoryMessage = historyMessage.replace(/<\/?[^>]+(>|$)/g, ""); - message = '"' + sanitizedHistoryMessage + '" ' + - "Open INVENTORY to see all activity."; - ui.notificationDisplayBanner(message); - } - } - } - } -} - -function isReturnedDataEmptyUpdates(data) { - var updatesArray = data.data.updates; - return updatesArray.length === 0; -} - -function isReturnedDataEmptyHistory(data) { - var historyArray = data.data.history; - return historyArray.length === 0; -} - -var DEVELOPER_MENU = "Developer"; -var MARKETPLACE_ITEM_TESTER_LABEL = "Marketplace Item Tester"; -var MARKETPLACE_ITEM_TESTER_QML_SOURCE = "hifi/commerce/marketplaceItemTester/MarketplaceItemTester.qml"; -function installMarketplaceItemTester() { - if (!Menu.menuExists(DEVELOPER_MENU)) { - Menu.addMenu(DEVELOPER_MENU); - } - if (!Menu.menuItemExists(DEVELOPER_MENU, MARKETPLACE_ITEM_TESTER_LABEL)) { - Menu.addMenuItem({ - menuName: DEVELOPER_MENU, - menuItemName: MARKETPLACE_ITEM_TESTER_LABEL, - isCheckable: false - }); - } - - Menu.menuItemEvent.connect(function (menuItem) { - if (menuItem === MARKETPLACE_ITEM_TESTER_LABEL) { - ui.open(MARKETPLACE_ITEM_TESTER_QML_SOURCE); - } - }); -} - -function uninstallMarketplaceItemTester() { - if (Menu.menuExists(DEVELOPER_MENU) && - Menu.menuItemExists(DEVELOPER_MENU, MARKETPLACE_ITEM_TESTER_LABEL) - ) { - Menu.removeMenuItem(DEVELOPER_MENU, MARKETPLACE_ITEM_TESTER_LABEL); - } -} - -var BUTTON_NAME = "INVENTORY"; -var WALLET_QML_SOURCE = "hifi/commerce/wallet/Wallet.qml"; -var SENDASSET_QML_SOURCE = "hifi/commerce/common/sendAsset/SendAsset.qml"; -var NOTIFICATION_POLL_TIMEOUT = 300000; -var ui; -function startup() { - var notificationPollEndpointArray = ["/api/v1/commerce/available_updates?per_page=10"]; - var notificationPollTimeoutMsArray = [NOTIFICATION_POLL_TIMEOUT]; - var notificationDataProcessPageArray = [notificationDataProcessPageUpdates]; - var notificationPollCallbackArray = [notificationPollCallbackUpdates]; - var notificationPollStopPaginatingConditionMetArray = [isReturnedDataEmptyUpdates]; - var notificationPollCaresAboutSinceArray = [false]; - - if (!WalletScriptingInterface.limitedCommerce) { - notificationPollEndpointArray[1] = "/api/v1/commerce/history?per_page=10"; - notificationPollTimeoutMsArray[1] = NOTIFICATION_POLL_TIMEOUT; - notificationDataProcessPageArray[1] = notificationDataProcessPageHistory; - notificationPollCallbackArray[1] = notificationPollCallbackHistory; - notificationPollStopPaginatingConditionMetArray[1] = isReturnedDataEmptyHistory; - notificationPollCaresAboutSinceArray[1] = true; - } - - ui = new AppUi({ - buttonName: BUTTON_NAME, - sortOrder: 10, - home: WALLET_QML_SOURCE, - additionalAppScreens: SENDASSET_QML_SOURCE, - onOpened: walletOpened, - onClosed: walletClosed, - onMessage: fromQml, - notificationPollEndpoint: notificationPollEndpointArray, - notificationPollTimeoutMs: notificationPollTimeoutMsArray, - notificationDataProcessPage: notificationDataProcessPageArray, - notificationPollCallback: notificationPollCallbackArray, - notificationPollStopPaginatingConditionMet: notificationPollStopPaginatingConditionMetArray, - notificationPollCaresAboutSince: notificationPollCaresAboutSinceArray - }); - GlobalServices.myUsernameChanged.connect(onUsernameChanged); - installMarketplaceItemTester(); -} - -var isUpdateOverlaysWired = false; -function off() { - if (isWired) { - Users.usernameFromIDReply.disconnect(usernameFromIDReply); - Controller.mousePressEvent.disconnect(handleMouseEvent); - Controller.mouseMoveEvent.disconnect(handleMouseMoveEvent); - triggerMapping.disable(); - triggerPressMapping.disable(); - isWired = false; - } - - if (isUpdateOverlaysWired) { - Script.update.disconnect(updateOverlays); - isUpdateOverlaysWired = false; - } - removeOverlays(); -} - -function shutdown() { - GlobalServices.myUsernameChanged.disconnect(onUsernameChanged); - deleteSendMoneyParticleEffect(); - uninstallMarketplaceItemTester(); - off(); -} - -// -// Run the functions. -// -startup(); -Script.scriptEnding.connect(shutdown); -}()); // END LOCAL_SCOPE diff --git a/scripts/simplifiedUI/system/controllers/+android_questInterface/controllerScripts.js b/scripts/simplifiedUI/system/controllers/+android_questInterface/controllerScripts.js deleted file mode 100644 index d313efaca1..0000000000 --- a/scripts/simplifiedUI/system/controllers/+android_questInterface/controllerScripts.js +++ /dev/null @@ -1,58 +0,0 @@ -"use strict"; - -// controllerScripts.js -// -// Created by David Rowe on 15 Mar 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 -// - -/* global Script, Menu */ - -var CONTOLLER_SCRIPTS = [ - "squeezeHands.js", - "controllerDisplayManager.js", - "toggleAdvancedMovementForHandControllers.js", - "controllerDispatcher.js", - "controllerModules/nearParentGrabOverlay.js", - "controllerModules/stylusInput.js", - "controllerModules/equipEntity.js", - "controllerModules/nearTrigger.js", - "controllerModules/webSurfaceLaserInput.js", - "controllerModules/inVREditMode.js", - "controllerModules/disableOtherModule.js", - "controllerModules/farTrigger.js", - "controllerModules/teleport.js", - "controllerModules/hudOverlayPointer.js", - "controllerModules/scaleEntity.js", - "controllerModules/nearGrabHyperLinkEntity.js", - "controllerModules/nearTabletHighlight.js", - "controllerModules/nearGrabEntity.js", - "controllerModules/farGrabEntity.js" -]; - -var DEBUG_MENU_ITEM = "Debug defaultScripts.js"; - -function runDefaultsTogether() { - for (var j in CONTOLLER_SCRIPTS) { - if (CONTOLLER_SCRIPTS.hasOwnProperty(j)) { - Script.include(CONTOLLER_SCRIPTS[j]); - } - } -} - -function runDefaultsSeparately() { - for (var i in CONTOLLER_SCRIPTS) { - if (CONTOLLER_SCRIPTS.hasOwnProperty(i)) { - Script.load(CONTOLLER_SCRIPTS[i]); - } - } -} - -if (Menu.isOptionChecked(DEBUG_MENU_ITEM)) { - runDefaultsSeparately(); -} else { - runDefaultsTogether(); -} diff --git a/scripts/simplifiedUI/system/controllers/controllerDispatcher.js b/scripts/simplifiedUI/system/controllers/controllerDispatcher.js deleted file mode 100644 index 0a9fa4dce1..0000000000 --- a/scripts/simplifiedUI/system/controllers/controllerDispatcher.js +++ /dev/null @@ -1,615 +0,0 @@ -"use strict"; - -// controllerDispatcher.js -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - -/* jslint bitwise: true */ - -/* global Script, Entities, Overlays, Controller, Vec3, Quat, getControllerWorldLocation, - controllerDispatcherPlugins:true, controllerDispatcherPluginsNeedSort:true, - LEFT_HAND, RIGHT_HAND, NEAR_GRAB_PICK_RADIUS, DEFAULT_SEARCH_SPHERE_DISTANCE, DISPATCHER_PROPERTIES, - getGrabPointSphereOffset, HMD, MyAvatar, Messages, findHandChildEntities, Picks, PickType, Pointers, - PointerManager, getGrabPointSphereOffset, HMD, MyAvatar, Messages, findHandChildEntities, Picks, PickType, Pointers, - PointerManager, print, Keyboard -*/ - -controllerDispatcherPlugins = {}; -controllerDispatcherPluginsNeedSort = false; - -Script.include("/~/system/libraries/utils.js"); -Script.include("/~/system/libraries/controllers.js"); -Script.include("/~/system/libraries/controllerDispatcherUtils.js"); - -(function() { - Script.include("/~/system/libraries/pointersUtils.js"); - - var NEAR_MAX_RADIUS = 0.1; - var NEAR_TABLET_MAX_RADIUS = 0.05; - - var TARGET_UPDATE_HZ = 60; // 50hz good enough, but we're using update - var BASIC_TIMER_INTERVAL_MS = 1000 / TARGET_UPDATE_HZ; - - var PROFILE = false; - var DEBUG = false; - var SHOW_GRAB_SPHERE = false; - - - if (typeof Test !== "undefined") { - PROFILE = true; - } - - function ControllerDispatcher() { - var _this = this; - this.lastInterval = Date.now(); - this.intervalCount = 0; - this.totalDelta = 0; - this.totalVariance = 0; - this.highVarianceCount = 0; - this.veryhighVarianceCount = 0; - this.orderedPluginNames = []; - this.tabletID = null; - this.blacklist = []; - this.pointerManager = new PointerManager(); - this.grabSphereOverlays = [null, null]; - this.targetIDs = {}; - - // a module can occupy one or more "activity" slots while it's running. If all the required slots for a module are - // not set to false (not in use), a module cannot start. When a module is using a slot, that module's name - // is stored as the value, rather than false. - this.activitySlots = { - head: false, - leftHand: false, - rightHand: false, - rightHandTrigger: false, - leftHandTrigger: false, - rightHandEquip: false, - leftHandEquip: false, - mouse: false - }; - - this.laserVisibleStatus = [false, false, false, false]; - this.laserLockStatus = [false, false, false, false]; - - this.slotsAreAvailableForPlugin = function (plugin) { - for (var i = 0; i < plugin.parameters.activitySlots.length; i++) { - if (_this.activitySlots[plugin.parameters.activitySlots[i]]) { - return false; // something is already using a slot which _this plugin requires - } - } - return true; - }; - - this.markSlots = function (plugin, pluginName) { - for (var i = 0; i < plugin.parameters.activitySlots.length; i++) { - _this.activitySlots[plugin.parameters.activitySlots[i]] = pluginName; - } - }; - - this.unmarkSlotsForPluginName = function (runningPluginName) { - // this is used to free activity-slots when a plugin is deactivated while it's running. - for (var activitySlot in _this.activitySlots) { - if (activitySlot.hasOwnProperty(activitySlot) && _this.activitySlots[activitySlot] === runningPluginName) { - _this.activitySlots[activitySlot] = false; - } - } - }; - - this.runningPluginNames = {}; - this.leftTriggerValue = 0; - this.leftTriggerClicked = 0; - this.rightTriggerValue = 0; - this.rightTriggerClicked = 0; - this.leftSecondaryValue = 0; - this.rightSecondaryValue = 0; - - this.leftTriggerPress = function (value) { - _this.leftTriggerValue = value; - }; - this.leftTriggerClick = function (value) { - _this.leftTriggerClicked = value; - }; - this.rightTriggerPress = function (value) { - _this.rightTriggerValue = value; - }; - this.rightTriggerClick = function (value) { - _this.rightTriggerClicked = value; - }; - this.leftSecondaryPress = function (value) { - _this.leftSecondaryValue = value; - }; - this.rightSecondaryPress = function (value) { - _this.rightSecondaryValue = value; - }; - - this.dataGatherers = {}; - this.dataGatherers.leftControllerLocation = function () { - return getControllerWorldLocation(Controller.Standard.LeftHand, true); - }; - this.dataGatherers.rightControllerLocation = function () { - return getControllerWorldLocation(Controller.Standard.RightHand, true); - }; - - this.updateTimings = function () { - _this.intervalCount++; - var thisInterval = Date.now(); - var deltaTimeMsec = thisInterval - _this.lastInterval; - var deltaTime = deltaTimeMsec / 1000; - _this.lastInterval = thisInterval; - - _this.totalDelta += deltaTimeMsec; - - var variance = Math.abs(deltaTimeMsec - BASIC_TIMER_INTERVAL_MS); - _this.totalVariance += variance; - - if (variance > 1) { - _this.highVarianceCount++; - } - - if (variance > 5) { - _this.veryhighVarianceCount++; - } - - return deltaTime; - }; - - this.setIgnorePointerItems = function() { - if (HMD.tabletID && HMD.tabletID !== this.tabletID) { - this.tabletID = HMD.tabletID; - Pointers.setIgnoreItems(_this.leftPointer, _this.blacklist); - Pointers.setIgnoreItems(_this.rightPointer, _this.blacklist); - } - }; - - this.update = function () { - try { - _this.updateInternal(); - } catch (e) { - print(e); - } - Script.setTimeout(_this.update, BASIC_TIMER_INTERVAL_MS); - }; - - this.updateInternal = function () { - if (PROFILE) { - Script.beginProfileRange("dispatch.pre"); - } - var sensorScaleFactor = MyAvatar.sensorToWorldScale; - var deltaTime = _this.updateTimings(); - _this.setIgnorePointerItems(); - - if (controllerDispatcherPluginsNeedSort) { - _this.orderedPluginNames = []; - for (var pluginName in controllerDispatcherPlugins) { - if (controllerDispatcherPlugins.hasOwnProperty(pluginName)) { - _this.orderedPluginNames.push(pluginName); - } - } - _this.orderedPluginNames.sort(function (a, b) { - return controllerDispatcherPlugins[a].parameters.priority - - controllerDispatcherPlugins[b].parameters.priority; - }); - - controllerDispatcherPluginsNeedSort = false; - } - - if (PROFILE) { - Script.endProfileRange("dispatch.pre"); - } - - if (PROFILE) { - Script.beginProfileRange("dispatch.gather"); - } - - var controllerLocations = [ - _this.dataGatherers.leftControllerLocation(), - _this.dataGatherers.rightControllerLocation() - ]; - - // find 3d overlays near each hand - var nearbyOverlayIDs = []; - var h; - for (h = LEFT_HAND; h <= RIGHT_HAND; h++) { - if (controllerLocations[h].valid) { - var nearbyOverlays = - Overlays.findOverlays(controllerLocations[h].position, NEAR_MAX_RADIUS * sensorScaleFactor); - - // Tablet and mini-tablet must be within NEAR_TABLET_MAX_RADIUS in order to be grabbed. - // Mini tablet can only be grabbed the hand it's displayed on. - var tabletIndex = nearbyOverlays.indexOf(HMD.tabletID); - var miniTabletIndex = nearbyOverlays.indexOf(HMD.miniTabletID); - if (tabletIndex !== -1 || miniTabletIndex !== -1) { - var closebyOverlays = - Overlays.findOverlays(controllerLocations[h].position, NEAR_TABLET_MAX_RADIUS * sensorScaleFactor); - // Assumes that the tablet and mini-tablet are not displayed at the same time. - if (tabletIndex !== -1 && closebyOverlays.indexOf(HMD.tabletID) === -1) { - nearbyOverlays.splice(tabletIndex, 1); - } - if (miniTabletIndex !== -1 && - ((closebyOverlays.indexOf(HMD.miniTabletID) === -1) || h !== HMD.miniTabletHand)) { - nearbyOverlays.splice(miniTabletIndex, 1); - } - } - - nearbyOverlays.sort(function (a, b) { - var aPosition = Overlays.getProperty(a, "position"); - var aDistance = Vec3.distance(aPosition, controllerLocations[h].position); - var bPosition = Overlays.getProperty(b, "position"); - var bDistance = Vec3.distance(bPosition, controllerLocations[h].position); - return aDistance - bDistance; - }); - - nearbyOverlayIDs.push(nearbyOverlays); - } else { - nearbyOverlayIDs.push([]); - } - } - - // find entities near each hand - var nearbyEntityProperties = [[], []]; - var nearbyEntityPropertiesByID = {}; - for (h = LEFT_HAND; h <= RIGHT_HAND; h++) { - if (controllerLocations[h].valid) { - var controllerPosition = controllerLocations[h].position; - var findRadius = NEAR_MAX_RADIUS * sensorScaleFactor; - - if (SHOW_GRAB_SPHERE) { - if (this.grabSphereOverlays[h]) { - Overlays.editOverlay(this.grabSphereOverlays[h], { position: controllerLocations[h].position }); - } else { - var grabSphereSize = findRadius * 2; - this.grabSphereOverlays[h] = Overlays.addOverlay("sphere", { - position: controllerLocations[h].position, - dimensions: { x: grabSphereSize, y: grabSphereSize, z: grabSphereSize }, - color: { red: 30, green: 30, blue: 255 }, - alpha: 0.3, - solid: true, - visible: true, - // lineWidth: 2.0, - drawInFront: false, - grabbable: false - }); - } - } - - var nearbyEntityIDs = Entities.findEntities(controllerPosition, findRadius); - for (var j = 0; j < nearbyEntityIDs.length; j++) { - var entityID = nearbyEntityIDs[j]; - var props = Entities.getEntityProperties(entityID, DISPATCHER_PROPERTIES); - props.id = entityID; - props.distance = Vec3.distance(props.position, controllerLocations[h].position); - nearbyEntityPropertiesByID[entityID] = props; - nearbyEntityProperties[h].push(props); - } - } - } - - // raypick for each controller - var rayPicks = [ - Pointers.getPrevPickResult(_this.leftPointer), - Pointers.getPrevPickResult(_this.rightPointer) - ]; - var hudRayPicks = [ - Pointers.getPrevPickResult(_this.leftHudPointer), - Pointers.getPrevPickResult(_this.rightHudPointer) - ]; - var mouseRayPick = Pointers.getPrevPickResult(_this.mouseRayPick); - // if the pickray hit something very nearby, put it into the nearby entities list - for (h = LEFT_HAND; h <= RIGHT_HAND; h++) { - - // XXX find a way to extract searchRay from samuel's stuff - rayPicks[h].searchRay = { - origin: controllerLocations[h].position, - direction: Quat.getUp(controllerLocations[h].orientation), - length: 1000 - }; - - if (rayPicks[h].type === Picks.INTERSECTED_ENTITY) { - // XXX check to make sure this one isn't already in nearbyEntityProperties? - if (rayPicks[h].distance < NEAR_GRAB_PICK_RADIUS * sensorScaleFactor) { - var nearEntityID = rayPicks[h].objectID; - var nearbyProps = Entities.getEntityProperties(nearEntityID, DISPATCHER_PROPERTIES); - nearbyProps.id = nearEntityID; - nearbyProps.distance = rayPicks[h].distance; - nearbyEntityPropertiesByID[nearEntityID] = nearbyProps; - nearbyEntityProperties[h].push(nearbyProps); - } - } - - // sort by distance from each hand - nearbyEntityProperties[h].sort(function (a, b) { - return a.distance - b.distance; - }); - } - - // sometimes, during a HMD snap-turn, an equipped or held item wont be near - // the hand when the findEntities is done. Gather up any hand-children here. - for (h = LEFT_HAND; h <= RIGHT_HAND; h++) { - var handChildrenIDs = findHandChildEntities(h); - handChildrenIDs.forEach(function (handChildID) { - if (handChildID in nearbyEntityPropertiesByID) { - return; - } - var props = Entities.getEntityProperties(handChildID, DISPATCHER_PROPERTIES); - props.id = handChildID; - nearbyEntityPropertiesByID[handChildID] = props; - }); - } - - // also make sure we have the properties from the current module's target - for (var tIDRunningPluginName in _this.runningPluginNames) { - if (_this.runningPluginNames.hasOwnProperty(tIDRunningPluginName)) { - var targetIDs = _this.targetIDs[tIDRunningPluginName]; - if (targetIDs) { - for (var k = 0; k < targetIDs.length; k++) { - var targetID = targetIDs[k]; - if (!nearbyEntityPropertiesByID[targetID]) { - var targetProps = Entities.getEntityProperties(targetID, DISPATCHER_PROPERTIES); - targetProps.id = targetID; - nearbyEntityPropertiesByID[targetID] = targetProps; - } - } - } - } - } - - // bundle up all the data about the current situation - var controllerData = { - triggerValues: [_this.leftTriggerValue, _this.rightTriggerValue], - triggerClicks: [_this.leftTriggerClicked, _this.rightTriggerClicked], - secondaryValues: [_this.leftSecondaryValue, _this.rightSecondaryValue], - controllerLocations: controllerLocations, - nearbyEntityProperties: nearbyEntityProperties, - nearbyEntityPropertiesByID: nearbyEntityPropertiesByID, - nearbyOverlayIDs: nearbyOverlayIDs, - rayPicks: rayPicks, - hudRayPicks: hudRayPicks, - mouseRayPick: mouseRayPick - }; - if (PROFILE) { - Script.endProfileRange("dispatch.gather"); - } - - if (PROFILE) { - Script.beginProfileRange("dispatch.isReady"); - } - // check for plugins that would like to start. ask in order of increasing priority value - for (var pluginIndex = 0; pluginIndex < _this.orderedPluginNames.length; pluginIndex++) { - var orderedPluginName = _this.orderedPluginNames[pluginIndex]; - var candidatePlugin = controllerDispatcherPlugins[orderedPluginName]; - - if (_this.slotsAreAvailableForPlugin(candidatePlugin)) { - if (PROFILE) { - Script.beginProfileRange("dispatch.isReady." + orderedPluginName); - } - var readiness = candidatePlugin.isReady(controllerData, deltaTime); - if (readiness.active) { - // this plugin will start. add it to the list of running plugins and mark the - // activity-slots which this plugin consumes as "in use" - _this.runningPluginNames[orderedPluginName] = true; - _this.markSlots(candidatePlugin, orderedPluginName); - _this.pointerManager.makePointerVisible(candidatePlugin.parameters.handLaser); - if (DEBUG) { - print("controllerDispatcher running " + orderedPluginName); - } - } - if (PROFILE) { - Script.endProfileRange("dispatch.isReady." + orderedPluginName); - } - } - } - if (PROFILE) { - Script.endProfileRange("dispatch.isReady"); - } - - if (PROFILE) { - Script.beginProfileRange("dispatch.run"); - } - // give time to running plugins - for (var runningPluginName in _this.runningPluginNames) { - if (_this.runningPluginNames.hasOwnProperty(runningPluginName)) { - var plugin = controllerDispatcherPlugins[runningPluginName]; - if (!plugin) { - // plugin was deactivated while running. find the activity-slots it was using and make - // them available. - delete _this.runningPluginNames[runningPluginName]; - _this.unmarkSlotsForPluginName(runningPluginName); - } else { - if (PROFILE) { - Script.beginProfileRange("dispatch.run." + runningPluginName); - } - var runningness = plugin.run(controllerData, deltaTime); - - if (DEBUG) { - if (JSON.stringify(_this.targetIDs[runningPluginName]) != JSON.stringify(runningness.targets)) { - print("controllerDispatcher targetIDs[" + runningPluginName + "] = " + - JSON.stringify(runningness.targets)); - } - } - - _this.targetIDs[runningPluginName] = runningness.targets; - if (!runningness.active) { - // plugin is finished running, for now. remove it from the list - // of running plugins and mark its activity-slots as "not in use" - delete _this.runningPluginNames[runningPluginName]; - delete _this.targetIDs[runningPluginName]; - if (DEBUG) { - print("controllerDispatcher deleted targetIDs[" + runningPluginName + "]"); - } - _this.markSlots(plugin, false); - _this.pointerManager.makePointerInvisible(plugin.parameters.handLaser); - if (DEBUG) { - print("controllerDispatcher stopping " + runningPluginName); - } - } - _this.pointerManager.lockPointerEnd(plugin.parameters.handLaser, runningness.laserLockInfo); - if (PROFILE) { - Script.endProfileRange("dispatch.run." + runningPluginName); - } - } - } - } - _this.pointerManager.updatePointersRenderState(controllerData.triggerClicks, controllerData.triggerValues); - if (PROFILE) { - Script.endProfileRange("dispatch.run"); - } - }; - - this.leftBlacklistTabletIDs = []; - this.rightBlacklistTabletIDs = []; - - this.setLeftBlacklist = function () { - Pointers.setIgnoreItems(_this.leftPointer, _this.blacklist.concat(_this.leftBlacklistTabletIDs)); - }; - this.setRightBlacklist = function () { - Pointers.setIgnoreItems(_this.rightPointer, _this.blacklist.concat(_this.rightBlacklistTabletIDs)); - }; - - this.setBlacklist = function() { - _this.setLeftBlacklist(); - _this.setRightBlacklist(); - }; - - var MAPPING_NAME = "com.highfidelity.controllerDispatcher"; - var mapping = Controller.newMapping(MAPPING_NAME); - mapping.from([Controller.Standard.RT]).peek().to(_this.rightTriggerPress); - mapping.from([Controller.Standard.RTClick]).peek().to(_this.rightTriggerClick); - mapping.from([Controller.Standard.LT]).peek().to(_this.leftTriggerPress); - mapping.from([Controller.Standard.LTClick]).peek().to(_this.leftTriggerClick); - - mapping.from([Controller.Standard.RB]).peek().to(_this.rightSecondaryPress); - mapping.from([Controller.Standard.LB]).peek().to(_this.leftSecondaryPress); - mapping.from([Controller.Standard.LeftGrip]).peek().to(_this.leftSecondaryPress); - mapping.from([Controller.Standard.RightGrip]).peek().to(_this.rightSecondaryPress); - - Controller.enableMapping(MAPPING_NAME); - - this.leftPointer = this.pointerManager.createPointer(false, PickType.Ray, { - joint: "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", - filter: Picks.PICK_OVERLAYS | Picks.PICK_ENTITIES | Picks.PICK_INCLUDE_NONCOLLIDABLE, - triggers: [{action: Controller.Standard.LTClick, button: "Focus"}, {action: Controller.Standard.LTClick, button: "Primary"}], - posOffset: getGrabPointSphereOffset(Controller.Standard.LeftHand, true), - hover: true, - scaleWithParent: true, - distanceScaleEnd: true, - hand: LEFT_HAND - }); - Keyboard.setLeftHandLaser(this.leftPointer); - this.rightPointer = this.pointerManager.createPointer(false, PickType.Ray, { - joint: "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND", - filter: Picks.PICK_OVERLAYS | Picks.PICK_ENTITIES | Picks.PICK_INCLUDE_NONCOLLIDABLE, - triggers: [{action: Controller.Standard.RTClick, button: "Focus"}, {action: Controller.Standard.RTClick, button: "Primary"}], - posOffset: getGrabPointSphereOffset(Controller.Standard.RightHand, true), - hover: true, - scaleWithParent: true, - distanceScaleEnd: true, - hand: RIGHT_HAND - }); - Keyboard.setRightHandLaser(this.rightPointer); - this.leftHudPointer = this.pointerManager.createPointer(true, PickType.Ray, { - joint: "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", - filter: Picks.PICK_HUD, - maxDistance: DEFAULT_SEARCH_SPHERE_DISTANCE, - posOffset: getGrabPointSphereOffset(Controller.Standard.LeftHand, true), - triggers: [{action: Controller.Standard.LTClick, button: "Focus"}, {action: Controller.Standard.LTClick, button: "Primary"}], - hover: true, - scaleWithParent: true, - distanceScaleEnd: true, - hand: LEFT_HAND - }); - this.rightHudPointer = this.pointerManager.createPointer(true, PickType.Ray, { - joint: "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND", - filter: Picks.PICK_HUD, - maxDistance: DEFAULT_SEARCH_SPHERE_DISTANCE, - posOffset: getGrabPointSphereOffset(Controller.Standard.RightHand, true), - triggers: [{action: Controller.Standard.RTClick, button: "Focus"}, {action: Controller.Standard.RTClick, button: "Primary"}], - hover: true, - scaleWithParent: true, - distanceScaleEnd: true, - hand: RIGHT_HAND - }); - - this.mouseRayPick = Pointers.createPointer(PickType.Ray, { - joint: "Mouse", - filter: Picks.PICK_OVERLAYS | Picks.PICK_ENTITIES | Picks.PICK_INCLUDE_NONCOLLIDABLE, - enabled: true - }); - this.handleMessage = function (channel, data, sender) { - var message; - if (sender === MyAvatar.sessionUUID) { - try { - if (channel === 'Hifi-Hand-RayPick-Blacklist') { - message = JSON.parse(data); - var action = message.action; - var id = message.id; - var index = _this.blacklist.indexOf(id); - - if (action === 'add' && index === -1) { - _this.blacklist.push(id); - _this.setBlacklist(); - } - - if (action === 'remove') { - if (index > -1) { - _this.blacklist.splice(index, 1); - _this.setBlacklist(); - } - } - - if (action === "tablet") { - var tabletIDs = message.blacklist ? - [HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID, HMD.homeButtonHighlightID] : - []; - if (message.hand === LEFT_HAND) { - _this.leftBlacklistTabletIDs = tabletIDs; - _this.setLeftBlacklist(); - } else { - _this.rightBlacklistTabletIDs = tabletIDs; - _this.setRightBlacklist(); - } - } - } - } catch (e) { - print("WARNING: handControllerGrab.js -- error parsing message: " + data); - } - } - }; - - this.cleanup = function () { - Controller.disableMapping(MAPPING_NAME); - _this.pointerManager.removePointers(); - Pointers.removePointer(this.mouseRayPick); - }; - } - - function mouseReleaseOnOverlay(overlayID, event) { - if (HMD.homeButtonID && overlayID === HMD.homeButtonID && event.button === "Primary") { - Messages.sendLocalMessage("home", overlayID); - } - } - - var HAPTIC_STYLUS_STRENGTH = 1.0; - var HAPTIC_STYLUS_DURATION = 20.0; - function mousePress(id, event) { - if (HMD.active) { - var runningPlugins = controllerDispatcher.runningPluginNames; - if (event.id === controllerDispatcher.leftPointer && event.button === "Primary" && runningPlugins.LeftWebSurfaceLaserInput) { - Controller.triggerHapticPulse(HAPTIC_STYLUS_STRENGTH, HAPTIC_STYLUS_DURATION, LEFT_HAND); - } else if (event.id === controllerDispatcher.rightPointer && event.button === "Primary" && runningPlugins.RightWebSurfaceLaserInput) { - Controller.triggerHapticPulse(HAPTIC_STYLUS_STRENGTH, HAPTIC_STYLUS_DURATION, RIGHT_HAND); - } - } - } - - Overlays.mouseReleaseOnOverlay.connect(mouseReleaseOnOverlay); - Overlays.mousePressOnOverlay.connect(mousePress); - Entities.mousePressOnEntity.connect(mousePress); - - var controllerDispatcher = new ControllerDispatcher(); - Messages.subscribe('Hifi-Hand-RayPick-Blacklist'); - Messages.messageReceived.connect(controllerDispatcher.handleMessage); - - Script.scriptEnding.connect(controllerDispatcher.cleanup); - Script.setTimeout(controllerDispatcher.update, BASIC_TIMER_INTERVAL_MS); -}()); diff --git a/scripts/simplifiedUI/system/controllers/controllerDisplay.js b/scripts/simplifiedUI/system/controllers/controllerDisplay.js deleted file mode 100644 index e40b761307..0000000000 --- a/scripts/simplifiedUI/system/controllers/controllerDisplay.js +++ /dev/null @@ -1,292 +0,0 @@ -// -// controllerDisplay.js -// -// Created by Anthony J. Thibault on 10/20/16 -// Originally created by Ryan Huffman on 9/21/2016 -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - -/* globals createControllerDisplay:true, deleteControllerDisplay:true, Controller, Overlays, Vec3, MyAvatar, Quat */ - -function clamp(value, min, max) { - if (value < min) { - return min; - } else if (value > max) { - return max; - } - return value; -} - -function resolveHardware(path) { - if (typeof path === 'string') { - var parts = path.split("."); - function resolveInner(base, path, i) { - if (i >= path.length) { - return base; - } - return resolveInner(base[path[i]], path, ++i); - } - return resolveInner(Controller.Hardware, parts, 0); - } - return path; -} - -var DEBUG = true; -function debug() { - if (DEBUG) { - var args = Array.prototype.slice.call(arguments); - args.unshift("controllerDisplay.js | "); - print.apply(this, args); - } -} - -createControllerDisplay = function(config) { - var controllerDisplay = { - overlays: [], - partOverlays: {}, - parts: {}, - mappingName: "mapping-display-" + Math.random(), - partValues: {}, - - setVisible: function(visible) { - for (var i = 0; i < this.overlays.length; ++i) { - Overlays.editOverlay(this.overlays[i], { - visible: visible - }); - } - }, - - setPartVisible: function(partName, visible) { - // Disabled - /* - if (partName in this.partOverlays) { - for (var i = 0; i < this.partOverlays[partName].length; ++i) { - Overlays.editOverlay(this.partOverlays[partName][i], { - //visible: visible - }); - } - } - */ - }, - - setLayerForPart: function(partName, layerName) { - if (partName in this.parts) { - var part = this.parts[partName]; - if (part.textureLayers && layerName in part.textureLayers) { - var layer = part.textureLayers[layerName]; - var textures = {}; - if (layer.defaultTextureURL) { - textures[part.textureName] = layer.defaultTextureURL; - } - for (var i = 0; i < this.partOverlays[partName].length; ++i) { - Overlays.editOverlay(this.partOverlays[partName][i], { - textures: textures - }); - } - } - } - }, - - resize: function(sensorScaleFactor) { - if (this.overlays.length >= 0) { - var controller = config.controllers[0]; - var position = controller.position; - - // first overlay is main body. - var overlayID = this.overlays[0]; - var localPosition = Vec3.multiply(sensorScaleFactor, Vec3.sum(Vec3.multiplyQbyV(controller.rotation, controller.naturalPosition), position)); - var dimensions = Vec3.multiply(sensorScaleFactor, controller.dimensions); - - Overlays.editOverlay(overlayID, { - dimensions: dimensions, - localPosition: localPosition - }); - - if (controller.parts) { - var i = 1; - for (var partName in controller.parts) { - overlayID = this.overlays[i++]; - var part = controller.parts[partName]; - localPosition = Vec3.subtract(part.naturalPosition, controller.naturalPosition); - var localRotation; - var value = this.partValues[partName]; - var offset, rotation; - if (value !== undefined) { - if (part.type === "linear") { - offset = Vec3.multiply(part.maxTranslation * value, part.axis); - localPosition = Vec3.sum(localPosition, offset); - localRotation = undefined; - } else if (part.type === "joystick") { - rotation = Quat.fromPitchYawRollDegrees(value.y * part.xHalfAngle, 0, value.x * part.yHalfAngle); - if (part.originOffset) { - offset = Vec3.multiplyQbyV(rotation, part.originOffset); - offset = Vec3.subtract(part.originOffset, offset); - } else { - offset = { x: 0, y: 0, z: 0 }; - } - localPosition = Vec3.sum(offset, localPosition); - localRotation = rotation; - } else if (part.type === "rotational") { - value = clamp(value, part.minValue, part.maxValue); - var pct = (value - part.minValue) / part.maxValue; - var angle = pct * part.maxAngle; - rotation = Quat.angleAxis(angle, part.axis); - if (part.origin) { - offset = Vec3.multiplyQbyV(rotation, part.origin); - offset = Vec3.subtract(offset, part.origin); - } else { - offset = { x: 0, y: 0, z: 0 }; - } - localPosition = Vec3.sum(offset, localPosition); - localRotation = rotation; - } - } - if (localRotation !== undefined) { - Overlays.editOverlay(overlayID, { - dimensions: Vec3.multiply(sensorScaleFactor, part.naturalDimensions), - localPosition: Vec3.multiply(sensorScaleFactor, localPosition), - localRotation: localRotation - }); - } else { - Overlays.editOverlay(overlayID, { - dimensions: Vec3.multiply(sensorScaleFactor, part.naturalDimensions), - localPosition: Vec3.multiply(sensorScaleFactor, localPosition) - }); - } - } - } - } - } - }; - - var mapping = Controller.newMapping(controllerDisplay.mappingName); - for (var i = 0; i < config.controllers.length; ++i) { - var controller = config.controllers[i]; - var position = controller.position; - var sensorScaleFactor = MyAvatar.sensorToWorldScale; - - if (controller.naturalPosition) { - position = Vec3.sum(Vec3.multiplyQbyV(controller.rotation, controller.naturalPosition), position); - } else { - controller.naturalPosition = { x: 0, y: 0, z: 0 }; - } - - var baseOverlayID = Overlays.addOverlay("model", { - url: controller.modelURL, - dimensions: Vec3.multiply(sensorScaleFactor, controller.dimensions), - localRotation: controller.rotation, - localPosition: Vec3.multiply(sensorScaleFactor, position), - parentID: MyAvatar.SELF_ID, - parentJointIndex: controller.jointIndex, - ignoreRayIntersection: true - }); - - controllerDisplay.overlays.push(baseOverlayID); - - if (controller.parts) { - for (var partName in controller.parts) { - var part = controller.parts[partName]; - var localPosition = Vec3.subtract(part.naturalPosition, controller.naturalPosition); - var localRotation = { x: 0, y: 0, z: 0, w: 1 }; - - controllerDisplay.parts[partName] = controller.parts[partName]; - - var properties = { - url: part.modelURL, - localPosition: localPosition, - localRotation: localRotation, - parentID: baseOverlayID, - ignoreRayIntersection: true - }; - - if (part.defaultTextureLayer) { - var textures = {}; - textures[part.textureName] = part.textureLayers[part.defaultTextureLayer].defaultTextureURL; - properties.textures = textures; - } - - var overlayID = Overlays.addOverlay("model", properties); - - if (part.type === "rotational") { - var input = resolveHardware(part.input); - mapping.from([input]).peek().to(function(partName) { - return function(value) { - // insert the most recent controller value into controllerDisplay.partValues. - controllerDisplay.partValues[partName] = value; - controllerDisplay.resize(MyAvatar.sensorToWorldScale); - }; - }(partName)); - } else if (part.type === "touchpad") { - var visibleInput = resolveHardware(part.visibleInput); - var xInput = resolveHardware(part.xInput); - var yInput = resolveHardware(part.yInput); - - // TODO: Touchpad inputs are currently only working for half - // of the touchpad. When that is fixed, it would be useful - // to update these to display the current finger position. - mapping.from([visibleInput]).peek().to(function(value) { - }); - mapping.from([xInput]).peek().to(function(value) { - }); - mapping.from([yInput]).peek().invert().to(function(value) { - }); - } else if (part.type === "joystick") { - (function(part, partName) { - var xInput = resolveHardware(part.xInput); - var yInput = resolveHardware(part.yInput); - mapping.from([xInput]).peek().to(function(value) { - // insert the most recent controller value into controllerDisplay.partValues. - if (controllerDisplay.partValues[partName]) { - controllerDisplay.partValues[partName].x = value; - } else { - controllerDisplay.partValues[partName] = {x: value, y: 0}; - } - controllerDisplay.resize(MyAvatar.sensorToWorldScale); - }); - mapping.from([yInput]).peek().to(function(value) { - // insert the most recent controller value into controllerDisplay.partValues. - if (controllerDisplay.partValues[partName]) { - controllerDisplay.partValues[partName].y = value; - } else { - controllerDisplay.partValues[partName] = {x: 0, y: value}; - } - controllerDisplay.resize(MyAvatar.sensorToWorldScale); - }); - })(part, partName); - - } else if (part.type === "linear") { - (function(part, partName) { - var input = resolveHardware(part.input); - mapping.from([input]).peek().to(function(value) { - // insert the most recent controller value into controllerDisplay.partValues. - controllerDisplay.partValues[partName] = value; - controllerDisplay.resize(MyAvatar.sensorToWorldScale); - }); - })(part, partName); - - } else if (part.type === "static") { - // do nothing - } else { - debug("TYPE NOT SUPPORTED: ", part.type); - } - - controllerDisplay.overlays.push(overlayID); - if (!(partName in controllerDisplay.partOverlays)) { - controllerDisplay.partOverlays[partName] = []; - } - controllerDisplay.partOverlays[partName].push(overlayID); - } - } - } - Controller.enableMapping(controllerDisplay.mappingName); - controllerDisplay.resize(MyAvatar.sensorToWorldScale); - return controllerDisplay; -}; - -deleteControllerDisplay = function(controllerDisplay) { - for (var i = 0; i < controllerDisplay.overlays.length; ++i) { - Overlays.deleteOverlay(controllerDisplay.overlays[i]); - } - Controller.disableMapping(controllerDisplay.mappingName); -}; diff --git a/scripts/simplifiedUI/system/controllers/controllerDisplayManager.js b/scripts/simplifiedUI/system/controllers/controllerDisplayManager.js deleted file mode 100644 index f93f8b1624..0000000000 --- a/scripts/simplifiedUI/system/controllers/controllerDisplayManager.js +++ /dev/null @@ -1,195 +0,0 @@ -// -// controllerDisplayManager.js -// -// Created by Anthony J. Thibault on 10/20/16 -// Originally created by Ryan Huffman on 9/21/2016 -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - -/* globals ControllerDisplayManager:true, createControllerDisplay, deleteControllerDisplay, - VIVE_CONTROLLER_CONFIGURATION_LEFT, VIVE_CONTROLLER_CONFIGURATION_RIGHT, Script, HMD, Controller, - MyAvatar, Overlays, TOUCH_CONTROLLER_CONFIGURATION_LEFT, TOUCH_CONTROLLER_CONFIGURATION_RIGHT, Messages */ -/* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ - -(function () { - -Script.include("controllerDisplay.js"); -Script.include("viveControllerConfiguration.js"); -Script.include("touchControllerConfiguration.js"); - -var HIDE_CONTROLLERS_ON_EQUIP = false; - -// -// Management of controller display -// -ControllerDisplayManager = function() { - var self = this; - var controllerLeft = null; - var controllerRight = null; - var controllerCheckerIntervalID = null; - - this.setLeftVisible = function(visible) { - if (controllerLeft) { - controllerLeft.setVisible(visible); - } - }; - - this.setRightVisible = function(visible) { - if (controllerRight) { - controllerRight.setVisible(visible); - } - }; - - function updateControllers() { - if (HMD.active && HMD.shouldShowHandControllers()) { - var leftConfig = null; - var rightConfig = null; - - if ("Vive" in Controller.Hardware) { - leftConfig = VIVE_CONTROLLER_CONFIGURATION_LEFT; - rightConfig = VIVE_CONTROLLER_CONFIGURATION_RIGHT; - } - - if ("OculusTouch" in Controller.Hardware) { - leftConfig = TOUCH_CONTROLLER_CONFIGURATION_LEFT; - rightConfig = TOUCH_CONTROLLER_CONFIGURATION_RIGHT; - } - - if (leftConfig !== null && rightConfig !== null) { - if (controllerLeft === null) { - controllerLeft = createControllerDisplay(leftConfig); - controllerLeft.setVisible(true); - } - if (controllerRight === null) { - controllerRight = createControllerDisplay(rightConfig); - controllerRight.setVisible(true); - } - // We've found the controllers, we no longer need to look for active controllers - if (controllerCheckerIntervalID) { - Script.clearInterval(controllerCheckerIntervalID); - controllerCheckerIntervalID = null; - } - - } else { - self.deleteControllerDisplays(); - if (!controllerCheckerIntervalID) { - controllerCheckerIntervalID = Script.setInterval(updateControllers, 1000); - } - } - } else { - // We aren't in HMD mode, we no longer need to look for active controllers - if (controllerCheckerIntervalID) { - Script.clearInterval(controllerCheckerIntervalID); - controllerCheckerIntervalID = null; - } - self.deleteControllerDisplays(); - } - } - - function resizeControllers(sensorScaleFactor) { - if (controllerLeft) { - controllerLeft.resize(sensorScaleFactor); - } - if (controllerRight) { - controllerRight.resize(sensorScaleFactor); - } - } - - var handleMessages = function(channel, message, sender) { - var i, data, name, visible; - if (!controllerLeft && !controllerRight) { - return; - } - - if (sender === MyAvatar.sessionUUID) { - if (channel === 'Controller-Display') { - data = JSON.parse(message); - name = data.name; - visible = data.visible; - if (controllerLeft) { - if (name in controllerLeft.annotations) { - for (i = 0; i < controllerLeft.annotations[name].length; ++i) { - Overlays.editOverlay(controllerLeft.annotations[name][i], { visible: visible }); - } - } - } - if (controllerRight) { - if (name in controllerRight.annotations) { - for (i = 0; i < controllerRight.annotations[name].length; ++i) { - Overlays.editOverlay(controllerRight.annotations[name][i], { visible: visible }); - } - } - } - } else if (channel === 'Controller-Display-Parts') { - data = JSON.parse(message); - for (name in data) { - visible = data[name]; - if (controllerLeft) { - controllerLeft.setPartVisible(name, visible); - } - if (controllerRight) { - controllerRight.setPartVisible(name, visible); - } - } - } else if (channel === 'Controller-Set-Part-Layer') { - data = JSON.parse(message); - for (name in data) { - var layer = data[name]; - if (controllerLeft) { - controllerLeft.setLayerForPart(name, layer); - } - if (controllerRight) { - controllerRight.setLayerForPart(name, layer); - } - } - } else if (channel === 'Hifi-Object-Manipulation') { - if (HIDE_CONTROLLERS_ON_EQUIP) { - data = JSON.parse(message); - visible = data.action !== 'equip'; - if (data.joint === "LeftHand") { - self.setLeftVisible(visible); - } else if (data.joint === "RightHand") { - self.setRightVisible(visible); - } - } - } - } - }; - - Messages.messageReceived.connect(handleMessages); - - this.deleteControllerDisplays = function() { - if (controllerLeft) { - deleteControllerDisplay(controllerLeft); - controllerLeft = null; - } - if (controllerRight) { - deleteControllerDisplay(controllerRight); - controllerRight = null; - } - }; - - this.destroy = function() { - Messages.messageReceived.disconnect(handleMessages); - - HMD.displayModeChanged.disconnect(updateControllers); - HMD.shouldShowHandControllersChanged.disconnect(updateControllers); - - self.deleteControllerDisplays(); - }; - - HMD.displayModeChanged.connect(updateControllers); - HMD.shouldShowHandControllersChanged.connect(updateControllers); - MyAvatar.sensorToWorldScaleChanged.connect(resizeControllers); - - updateControllers(); -}; - -var controllerDisplayManager = new ControllerDisplayManager(); - -Script.scriptEnding.connect(function () { - controllerDisplayManager.destroy(); -}); - -}()); diff --git a/scripts/simplifiedUI/system/controllers/controllerModules/disableOtherModule.js b/scripts/simplifiedUI/system/controllers/controllerModules/disableOtherModule.js deleted file mode 100644 index 7636c56f65..0000000000 --- a/scripts/simplifiedUI/system/controllers/controllerModules/disableOtherModule.js +++ /dev/null @@ -1,83 +0,0 @@ -"use strict"; - -// disableOtherModule.js -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - - -/* global Script, MyAvatar, RIGHT_HAND, LEFT_HAND, enableDispatcherModule, disableDispatcherModule, - makeDispatcherModuleParameters, makeRunningValues, getEnabledModuleByName, Messages -*/ - -Script.include("/~/system/libraries/controllerDispatcherUtils.js"); - -(function() { - function DisableModules(hand) { - this.hand = hand; - this.disableModules = false; - this.parameters = makeDispatcherModuleParameters( - 90, - this.hand === RIGHT_HAND ? - ["rightHand", "rightHandEquip", "rightHandTrigger"] : - ["leftHand", "leftHandEquip", "leftHandTrigger"], - [], - 100); - - this.isReady = function(controllerData) { - if (this.disableModules) { - return makeRunningValues(true, [], []); - } - return false; - }; - - this.run = function(controllerData) { - var teleportModuleName = this.hand === RIGHT_HAND ? "RightTeleporter" : "LeftTeleporter"; - var teleportModule = getEnabledModuleByName(teleportModuleName); - - if (teleportModule) { - var ready = teleportModule.isReady(controllerData); - if (ready.active) { - return makeRunningValues(false, [], []); - } - } - if (!this.disableModules) { - return makeRunningValues(false, [], []); - } - return makeRunningValues(true, [], []); - }; - } - - var leftDisableModules = new DisableModules(LEFT_HAND); - var rightDisableModules = new DisableModules(RIGHT_HAND); - - enableDispatcherModule("LeftDisableModules", leftDisableModules); - enableDispatcherModule("RightDisableModules", rightDisableModules); - function handleMessage(channel, message, sender) { - if (sender === MyAvatar.sessionUUID) { - if (channel === 'Hifi-Hand-Disabler') { - if (message === 'left') { - leftDisableModules.disableModules = true; - } else if (message === 'right') { - rightDisableModules.disableModules = true; - } else if (message === 'both') { - leftDisableModules.disableModules = true; - rightDisableModules.disableModules = true; - } else if (message === 'none') { - leftDisableModules.disableModules = false; - rightDisableModules.disableModules = false; - } else { - print("disableOtherModule -- unknown command: " + message); - } - } - } - } - - Messages.subscribe('Hifi-Hand-Disabler'); - function cleanup() { - disableDispatcherModule("LeftDisableModules"); - disableDispatcherModule("RightDisableModules"); - } - Messages.messageReceived.connect(handleMessage); - Script.scriptEnding.connect(cleanup); -}()); diff --git a/scripts/simplifiedUI/system/controllers/controllerModules/equipEntity.js b/scripts/simplifiedUI/system/controllers/controllerModules/equipEntity.js deleted file mode 100644 index 54b56ff271..0000000000 --- a/scripts/simplifiedUI/system/controllers/controllerModules/equipEntity.js +++ /dev/null @@ -1,867 +0,0 @@ -"use strict"; - -// equipEntity.js -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - - -/* global Script, Entities, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND, Camera, print, getControllerJointIndex, - enableDispatcherModule, disableDispatcherModule, Messages, makeDispatcherModuleParameters, - makeRunningValues, Settings, entityHasActions, Vec3, Overlays, flatten, Xform, getControllerWorldLocation, ensureDynamic, - entityIsCloneable, cloneEntity, DISPATCHER_PROPERTIES, Uuid, isInEditMode, getGrabbableData, - entityIsEquippable, HMD -*/ - -Script.include("/~/system/libraries/Xform.js"); -Script.include("/~/system/libraries/controllerDispatcherUtils.js"); -Script.include("/~/system/libraries/controllers.js"); -Script.include("/~/system/libraries/cloneEntityUtils.js"); - - -var DEFAULT_SPHERE_MODEL_URL = "http://hifi-content.s3.amazonaws.com/alan/dev/equip-Fresnel-3.fbx"; -var EQUIP_SPHERE_SCALE_FACTOR = 0.65; - - -// Each overlayInfoSet describes a single equip hotspot. -// It is an object with the following keys: -// timestamp - last time this object was updated, used to delete stale hotspot overlays. -// entityID - entity assosicated with this hotspot -// localPosition - position relative to the entity -// hotspot - hotspot object -// overlays - array of overlay objects created by Overlay.addOverlay() -// currentSize - current animated scale value -// targetSize - the target of our scale animations -// type - "sphere" or "model". -function EquipHotspotBuddy() { - // holds map from {string} hotspot.key to {object} overlayInfoSet. - this.map = {}; - - // array of all hotspots that are highlighed. - this.highlightedHotspots = []; -} -EquipHotspotBuddy.prototype.clear = function() { - var keys = Object.keys(this.map); - for (var i = 0; i < keys.length; i++) { - var overlayInfoSet = this.map[keys[i]]; - this.deleteOverlayInfoSet(overlayInfoSet); - } - this.map = {}; - this.highlightedHotspots = []; -}; -EquipHotspotBuddy.prototype.highlightHotspot = function(hotspot) { - this.highlightedHotspots.push(hotspot.key); -}; -EquipHotspotBuddy.prototype.updateHotspot = function(hotspot, timestamp) { - var overlayInfoSet = this.map[hotspot.key]; - if (!overlayInfoSet) { - // create a new overlayInfoSet - overlayInfoSet = { - timestamp: timestamp, - entityID: hotspot.entityID, - localPosition: hotspot.localPosition, - hotspot: hotspot, - currentSize: 0, - targetSize: 1, - overlays: [] - }; - - var dimensions = hotspot.radius * 2 * EQUIP_SPHERE_SCALE_FACTOR; - - if (hotspot.indicatorURL) { - dimensions = hotspot.indicatorScale; - } - - // override default sphere with a user specified model, if it exists. - overlayInfoSet.overlays.push(Overlays.addOverlay("model", { - name: "hotspot overlay", - url: hotspot.indicatorURL ? hotspot.indicatorURL : DEFAULT_SPHERE_MODEL_URL, - position: hotspot.worldPosition, - rotation: { - x: 0, - y: 0, - z: 0, - w: 1 - }, - dimensions: dimensions, - ignoreRayIntersection: true - })); - overlayInfoSet.type = "model"; - this.map[hotspot.key] = overlayInfoSet; - } else { - overlayInfoSet.timestamp = timestamp; - } -}; -EquipHotspotBuddy.prototype.updateHotspots = function(hotspots, timestamp) { - var _this = this; - hotspots.forEach(function(hotspot) { - _this.updateHotspot(hotspot, timestamp); - }); - this.highlightedHotspots = []; -}; -EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerData) { - - var HIGHLIGHT_SIZE = 1.1; - var NORMAL_SIZE = 1.0; - - var keys = Object.keys(this.map); - for (var i = 0; i < keys.length; i++) { - var overlayInfoSet = this.map[keys[i]]; - - // this overlayInfo is highlighted. - if (this.highlightedHotspots.indexOf(keys[i]) !== -1) { - overlayInfoSet.targetSize = HIGHLIGHT_SIZE; - } else { - overlayInfoSet.targetSize = NORMAL_SIZE; - } - - // start to fade out this hotspot. - if (overlayInfoSet.timestamp !== timestamp) { - overlayInfoSet.targetSize = 0; - } - - // animate the size. - var SIZE_TIMESCALE = 0.1; - var tau = deltaTime / SIZE_TIMESCALE; - if (tau > 1.0) { - tau = 1.0; - } - overlayInfoSet.currentSize += (overlayInfoSet.targetSize - overlayInfoSet.currentSize) * tau; - - if (overlayInfoSet.timestamp !== timestamp && overlayInfoSet.currentSize <= 0.05) { - // this is an old overlay, that has finished fading out, delete it! - overlayInfoSet.overlays.forEach(Overlays.deleteOverlay); - delete this.map[keys[i]]; - } else { - // update overlay position, rotation to follow the object it's attached to. - var props = controllerData.nearbyEntityPropertiesByID[overlayInfoSet.entityID]; - if (props) { - var entityXform = new Xform(props.rotation, props.position); - var position = entityXform.xformPoint(overlayInfoSet.localPosition); - - var dimensions; - if (overlayInfoSet.hotspot.indicatorURL) { - var ratio = overlayInfoSet.currentSize / overlayInfoSet.targetSize; - dimensions = { - x: overlayInfoSet.hotspot.dimensions.x * ratio, - y: overlayInfoSet.hotspot.dimensions.y * ratio, - z: overlayInfoSet.hotspot.dimensions.z * ratio - }; - } else { - dimensions = (overlayInfoSet.hotspot.radius / 2) * overlayInfoSet.currentSize; - } - - overlayInfoSet.overlays.forEach(function(overlay) { - Overlays.editOverlay(overlay, { - position: position, - rotation: props.rotation, - dimensions: dimensions - }); - }); - } else { - overlayInfoSet.overlays.forEach(Overlays.deleteOverlay); - delete this.map[keys[i]]; - } - } - } -}; - - -(function() { - - var ATTACH_POINT_SETTINGS = "io.highfidelity.attachPoints"; - - var HAPTIC_PULSE_STRENGTH = 1.0; - var HAPTIC_PULSE_DURATION = 13.0; - var HAPTIC_TEXTURE_STRENGTH = 0.1; - var HAPTIC_TEXTURE_DURATION = 3.0; - var HAPTIC_TEXTURE_DISTANCE = 0.002; - var HAPTIC_DEQUIP_STRENGTH = 0.75; - var HAPTIC_DEQUIP_DURATION = 50.0; - - var TRIGGER_SMOOTH_RATIO = 0.1; // Time averaging of trigger - 0.0 disables smoothing - var TRIGGER_OFF_VALUE = 0.1; - var TRIGGER_ON_VALUE = TRIGGER_OFF_VALUE + 0.05; // Squeezed just enough to activate search or near grab - var BUMPER_ON_VALUE = 0.5; - var ATTACHPOINT_MAX_DISTANCE = 3.0; - - // var EMPTY_PARENT_ID = "{00000000-0000-0000-0000-000000000000}"; - - var UNEQUIP_KEY = "u"; - - function getWearableData(props) { - if (props.grab.equippable) { - return { - joints: { - LeftHand: [ props.grab.equippableLeftPosition, props.grab.equippableLeftRotation ], - RightHand: [ props.grab.equippableRightPosition, props.grab.equippableRightRotation ] - }, - indicatorURL: props.grab.equippableIndicatorURL, - indicatorScale: props.grab.equippableIndicatorScale, - indicatorOffset: props.grab.equippableIndicatorOffset - }; - } else { - return null; - } - } - - function getAttachPointSettings() { - try { - var str = Settings.getValue(ATTACH_POINT_SETTINGS); - if (str === "false" || str === "") { - return {}; - } else { - return JSON.parse(str); - } - } catch (err) { - print("Error parsing attachPointSettings: " + err); - return {}; - } - } - - function setAttachPointSettings(attachPointSettings) { - var str = JSON.stringify(attachPointSettings); - Settings.setValue(ATTACH_POINT_SETTINGS, str); - } - - function getAttachPointForHotspotFromSettings(hotspot, hand) { - var skeletonModelURL = MyAvatar.skeletonModelURL; - var attachPointSettings = getAttachPointSettings(); - var avatarSettingsData = attachPointSettings[skeletonModelURL]; - if (avatarSettingsData) { - var jointName = (hand === RIGHT_HAND) ? "RightHand" : "LeftHand"; - var joints = avatarSettingsData[hotspot.key]; - if (joints) { - // make sure they are reasonable - if (joints[jointName] && joints[jointName][0] && - Vec3.length(joints[jointName][0]) > ATTACHPOINT_MAX_DISTANCE) { - print("equipEntity -- Warning: rejecting settings attachPoint " + Vec3.length(joints[jointName][0])); - return undefined; - } - return joints[jointName]; - } - } - return undefined; - } - - function storeAttachPointForHotspotInSettings(hotspot, hand, offsetPosition, offsetRotation) { - var attachPointSettings = getAttachPointSettings(); - var skeletonModelURL = MyAvatar.skeletonModelURL; - var avatarSettingsData = attachPointSettings[skeletonModelURL]; - if (!avatarSettingsData) { - avatarSettingsData = {}; - attachPointSettings[skeletonModelURL] = avatarSettingsData; - } - var jointName = (hand === RIGHT_HAND) ? "RightHand" : "LeftHand"; - var joints = avatarSettingsData[hotspot.key]; - if (!joints) { - joints = {}; - avatarSettingsData[hotspot.key] = joints; - } - joints[jointName] = [offsetPosition, offsetRotation]; - setAttachPointSettings(attachPointSettings); - } - - function clearAttachPoints() { - setAttachPointSettings({}); - } - - function EquipEntity(hand) { - this.hand = hand; - this.targetEntityID = null; - this.prevHandIsUpsideDown = false; - this.triggerValue = 0; - this.messageGrabEntity = false; - this.grabEntityProps = null; - this.shouldSendStart = false; - this.equipedWithSecondary = false; - this.handHasBeenRightsideUp = false; - - this.parameters = makeDispatcherModuleParameters( - 115, - this.hand === RIGHT_HAND ? ["rightHand", "rightHandEquip"] : ["leftHand", "leftHandEquip"], - [], - 100); - - var equipHotspotBuddy = new EquipHotspotBuddy(); - - this.setMessageGrabData = function(entityProperties) { - if (entityProperties) { - this.messageGrabEntity = true; - this.grabEntityProps = entityProperties; - } - }; - - // returns a list of all equip-hotspots assosiated with this entity. - // @param {UUID} entityID - // @returns {Object[]} array of objects with the following fields. - // * key {string} a string that can be used to uniquely identify this hotspot - // * entityID {UUID} - // * localPosition {Vec3} position of the hotspot in object space. - // * worldPosition {vec3} position of the hotspot in world space. - // * radius {number} radius of equip hotspot - // * joints {Object} keys are joint names values are arrays of two elements: - // offset position {Vec3} and offset rotation {Quat}, both are in the coordinate system of the joint. - // * indicatorURL {string} url for model to use instead of default sphere. - // * indicatorScale {Vec3} scale factor for model - this.collectEquipHotspots = function(props) { - var result = []; - var entityID = props.id; - var entityXform = new Xform(props.rotation, props.position); - - var wearableProps = getWearableData(props); - var sensorToScaleFactor = MyAvatar.sensorToWorldScale; - if (wearableProps && wearableProps.joints) { - result.push({ - key: entityID.toString() + "0", - entityID: entityID, - localPosition: wearableProps.indicatorOffset, - worldPosition: entityXform.pos, - radius: ((wearableProps.indicatorScale.x + - wearableProps.indicatorScale.y + - wearableProps.indicatorScale.z) / 3) * sensorToScaleFactor, - dimensions: wearableProps.indicatorScale, - joints: wearableProps.joints, - indicatorURL: wearableProps.indicatorURL, - indicatorScale: wearableProps.indicatorScale, - }); - } - return result; - }; - - this.hotspotIsEquippable = function(hotspot, controllerData) { - var props = controllerData.nearbyEntityPropertiesByID[hotspot.entityID]; - - var hasParent = true; - if (props.parentID === Uuid.NULL) { - hasParent = false; - } - - if (hasParent || entityHasActions(hotspot.entityID)) { - return false; - } - - return true; - }; - - this.handToController = function() { - return (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand; - }; - - this.updateSmoothedTrigger = function(controllerData) { - var triggerValue = controllerData.triggerValues[this.hand]; - // smooth out trigger value - this.triggerValue = (this.triggerValue * TRIGGER_SMOOTH_RATIO) + - (triggerValue * (1.0 - TRIGGER_SMOOTH_RATIO)); - }; - - this.triggerSmoothedGrab = function() { - return this.triggerClicked; - }; - - this.triggerSmoothedSqueezed = function() { - return this.triggerValue > TRIGGER_ON_VALUE; - }; - - this.triggerSmoothedReleased = function() { - return this.triggerValue < TRIGGER_OFF_VALUE; - }; - - this.secondaryReleased = function() { - return this.rawSecondaryValue < BUMPER_ON_VALUE; - }; - - this.secondarySmoothedSqueezed = function() { - return this.rawSecondaryValue > BUMPER_ON_VALUE; - }; - - this.chooseNearEquipHotspots = function(candidateEntityProps, controllerData) { - var _this = this; - var collectedHotspots = flatten(candidateEntityProps.map(function(props) { - return _this.collectEquipHotspots(props); - })); - var controllerLocation = controllerData.controllerLocations[_this.hand]; - var worldControllerPosition = controllerLocation.position; - var equippableHotspots = collectedHotspots.filter(function(hotspot) { - var hotspotDistance = Vec3.distance(hotspot.worldPosition, worldControllerPosition); - return _this.hotspotIsEquippable(hotspot, controllerData) && - hotspotDistance < hotspot.radius; - }); - return equippableHotspots; - }; - - this.cloneHotspot = function(props, controllerData) { - if (entityIsCloneable(props)) { - var cloneID = cloneEntity(props); - return cloneID; - } - - return null; - }; - - this.chooseBestEquipHotspot = function(candidateEntityProps, controllerData) { - var equippableHotspots = this.chooseNearEquipHotspots(candidateEntityProps, controllerData); - if (equippableHotspots.length > 0) { - // sort by distance; - var controllerLocation = controllerData.controllerLocations[this.hand]; - var worldControllerPosition = controllerLocation.position; - equippableHotspots.sort(function(a, b) { - var aDistance = Vec3.distance(a.worldPosition, worldControllerPosition); - var bDistance = Vec3.distance(b.worldPosition, worldControllerPosition); - return aDistance - bDistance; - }); - return equippableHotspots[0]; - } else { - return null; - } - }; - - this.dropGestureReset = function() { - this.prevHandIsUpsideDown = false; - }; - - this.dropGestureProcess = function (deltaTime) { - var worldHandRotation = getControllerWorldLocation(this.handToController(), true).orientation; - var localHandUpAxis = this.hand === RIGHT_HAND ? { x: 1, y: 0, z: 0 } : { x: -1, y: 0, z: 0 }; - var worldHandUpAxis = Vec3.multiplyQbyV(worldHandRotation, localHandUpAxis); - var DOWN = { x: 0, y: -1, z: 0 }; - - var DROP_ANGLE = Math.PI / 3; - var HYSTERESIS_FACTOR = 1.1; - var ROTATION_ENTER_THRESHOLD = Math.cos(DROP_ANGLE); - var ROTATION_EXIT_THRESHOLD = Math.cos(DROP_ANGLE * HYSTERESIS_FACTOR); - var rotationThreshold = this.prevHandIsUpsideDown ? ROTATION_EXIT_THRESHOLD : ROTATION_ENTER_THRESHOLD; - - var handIsUpsideDown = false; - if (Vec3.dot(worldHandUpAxis, DOWN) > rotationThreshold) { - handIsUpsideDown = true; - } - - if (handIsUpsideDown !== this.prevHandIsUpsideDown) { - this.prevHandIsUpsideDown = handIsUpsideDown; - Controller.triggerHapticPulse(HAPTIC_DEQUIP_STRENGTH, HAPTIC_DEQUIP_DURATION, this.hand); - } - - return handIsUpsideDown; - }; - - this.clearEquipHaptics = function() { - this.prevPotentialEquipHotspot = null; - }; - - this.updateEquipHaptics = function(potentialEquipHotspot, currentLocation) { - if (potentialEquipHotspot && !this.prevPotentialEquipHotspot || - !potentialEquipHotspot && this.prevPotentialEquipHotspot) { - Controller.triggerHapticPulse(HAPTIC_TEXTURE_STRENGTH, HAPTIC_TEXTURE_DURATION, this.hand); - this.lastHapticPulseLocation = currentLocation; - } else if (potentialEquipHotspot && - Vec3.distance(this.lastHapticPulseLocation, currentLocation) > HAPTIC_TEXTURE_DISTANCE) { - Controller.triggerHapticPulse(HAPTIC_TEXTURE_STRENGTH, HAPTIC_TEXTURE_DURATION, this.hand); - this.lastHapticPulseLocation = currentLocation; - } - this.prevPotentialEquipHotspot = potentialEquipHotspot; - }; - - this.startEquipEntity = function (controllerData) { - var _this = this; - - this.dropGestureReset(); - this.clearEquipHaptics(); - Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); - - var grabbedProperties = Entities.getEntityProperties(this.targetEntityID, DISPATCHER_PROPERTIES); - var grabData = getGrabbableData(grabbedProperties); - - // if an object is "equipped" and has a predefined offset, use it. - if (this.grabbedHotspot) { - var offsets = getAttachPointForHotspotFromSettings(this.grabbedHotspot, this.hand); - if (offsets) { - this.offsetPosition = offsets[0]; - this.offsetRotation = offsets[1]; - } else { - var handJointName = this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"; - if (this.grabbedHotspot.joints[handJointName]) { - this.offsetPosition = this.grabbedHotspot.joints[handJointName][0]; - this.offsetRotation = this.grabbedHotspot.joints[handJointName][1]; - } - } - } - - var handJointIndex; - if (HMD.mounted && HMD.isHandControllerAvailable() && grabData.grabFollowsController) { - handJointIndex = this.controllerJointIndex; - } else { - handJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"); - } - - var reparentProps = { - parentID: MyAvatar.SELF_ID, - parentJointIndex: handJointIndex, - localVelocity: {x: 0, y: 0, z: 0}, - localAngularVelocity: {x: 0, y: 0, z: 0}, - localPosition: this.offsetPosition, - localRotation: this.offsetRotation - }; - - var isClone = false; - if (entityIsCloneable(grabbedProperties)) { - var cloneID = this.cloneHotspot(grabbedProperties, controllerData); - this.targetEntityID = cloneID; - controllerData.nearbyEntityPropertiesByID[this.targetEntityID] = grabbedProperties; - isClone = true; - } else if (grabbedProperties.locked) { - this.grabbedHotspot = null; - this.targetEntityID = null; - return; - } - - - // HACK -- when - // https://highfidelity.fogbugz.com/f/cases/21767/entity-edits-shortly-after-an-add-often-fail - // is resolved, this can just be an editEntity rather than a setTimeout. - this.editDelayTimeout = Script.setTimeout(function () { - _this.editDelayTimeout = null; - Entities.editEntity(_this.targetEntityID, reparentProps); - }, 100); - - // we don't want to send startEquip message until the trigger is released. otherwise, - // guns etc will fire right as they are equipped. - this.shouldSendStart = true; - - Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({ - action: 'equip', - grabbedEntity: this.targetEntityID, - joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand" - })); - - var grabEquipCheck = function() { - var args = [_this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; - Entities.callEntityMethod(_this.targetEntityID, "startEquip", args); - }; - - if (isClone) { - // 100 ms seems to be sufficient time to force the check even occur after the object has been initialized. - Script.setTimeout(grabEquipCheck, 100); - } - }; - - this.endEquipEntity = function () { - - if (this.editDelayTimeout) { - Script.clearTimeout(this.editDelayTimeout); - this.editDelayTimeout = null; - } - - this.storeAttachPointInSettings(); - Entities.editEntity(this.targetEntityID, { - parentID: Uuid.NULL, - parentJointIndex: -1 - }); - - var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; - Entities.callEntityMethod(this.targetEntityID, "releaseEquip", args); - - Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({ - action: 'release', - grabbedEntity: this.targetEntityID, - joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand" - })); - - ensureDynamic(this.targetEntityID); - this.targetEntityID = null; - this.messageGrabEntity = false; - this.grabEntityProps = null; - }; - - this.updateInputs = function (controllerData) { - this.rawTriggerValue = controllerData.triggerValues[this.hand]; - this.triggerClicked = controllerData.triggerClicks[this.hand]; - this.rawSecondaryValue = controllerData.secondaryValues[this.hand]; - this.updateSmoothedTrigger(controllerData); - }; - - this.checkNearbyHotspots = function (controllerData, deltaTime, timestamp) { - this.controllerJointIndex = getControllerJointIndex(this.hand); - - if (this.triggerSmoothedReleased() && this.secondaryReleased()) { - this.waitForTriggerRelease = false; - } - - var controllerLocation = getControllerWorldLocation(this.handToController(), true); - var worldHandPosition = controllerLocation.position; - var candidateEntityProps = controllerData.nearbyEntityProperties[this.hand]; - - - var potentialEquipHotspot = null; - if (this.messageGrabEntity) { - var hotspots = this.collectEquipHotspots(this.grabEntityProps); - if (hotspots.length > -1) { - potentialEquipHotspot = hotspots[0]; - } - } else { - potentialEquipHotspot = this.chooseBestEquipHotspot(candidateEntityProps, controllerData); - } - - if (!this.waitForTriggerRelease) { - this.updateEquipHaptics(potentialEquipHotspot, worldHandPosition); - } - - var nearEquipHotspots = this.chooseNearEquipHotspots(candidateEntityProps, controllerData); - equipHotspotBuddy.updateHotspots(nearEquipHotspots, timestamp); - if (potentialEquipHotspot) { - equipHotspotBuddy.highlightHotspot(potentialEquipHotspot); - } - - equipHotspotBuddy.update(deltaTime, timestamp, controllerData); - - // if the potentialHotspot is cloneable, clone it and return it - // if the potentialHotspot is not cloneable and locked return null - if (potentialEquipHotspot && - (((this.triggerSmoothedSqueezed() || this.secondarySmoothedSqueezed()) && !this.waitForTriggerRelease) || - this.messageGrabEntity)) { - this.grabbedHotspot = potentialEquipHotspot; - this.targetEntityID = this.grabbedHotspot.entityID; - this.startEquipEntity(controllerData); - this.equipedWithSecondary = this.secondarySmoothedSqueezed(); - return makeRunningValues(true, [this.targetEntityID], []); - } else { - return makeRunningValues(false, [], []); - } - }; - - this.isTargetIDValid = function(controllerData) { - var entityProperties = controllerData.nearbyEntityPropertiesByID[this.targetEntityID]; - return entityProperties && "type" in entityProperties; - }; - - this.isReady = function (controllerData, deltaTime) { - var timestamp = Date.now(); - this.updateInputs(controllerData); - this.handHasBeenRightsideUp = false; - return this.checkNearbyHotspots(controllerData, deltaTime, timestamp); - }; - - this.run = function (controllerData, deltaTime) { - var timestamp = Date.now(); - this.updateInputs(controllerData); - - if (!this.messageGrabEntity && !this.isTargetIDValid(controllerData)) { - this.endEquipEntity(); - return makeRunningValues(false, [], []); - } - - if (!this.targetEntityID) { - return this.checkNearbyHotspots(controllerData, deltaTime, timestamp); - } - - if (controllerData.secondaryValues[this.hand] && !this.equipedWithSecondary) { - // this.secondaryReleased() will always be true when not depressed - // so we cannot simply rely on that for release - ensure that the - // trigger was first "prepared" by being pushed in before the release - this.preparingHoldRelease = true; - } - - if (this.preparingHoldRelease && !controllerData.secondaryValues[this.hand]) { - // we have an equipped object and the secondary trigger was released - // short-circuit the other checks and release it - this.preparingHoldRelease = false; - this.endEquipEntity(); - return makeRunningValues(false, [], []); - } - - var handIsUpsideDown = this.dropGestureProcess(deltaTime); - var dropDetected = false; - if (this.handHasBeenRightsideUp) { - dropDetected = handIsUpsideDown; - } - if (!handIsUpsideDown) { - this.handHasBeenRightsideUp = true; - } - - if (this.triggerSmoothedReleased() || this.secondaryReleased()) { - if (this.shouldSendStart) { - // we don't want to send startEquip message until the trigger is released. otherwise, - // guns etc will fire right as they are equipped. - var startArgs = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; - Entities.callEntityMethod(this.targetEntityID, "startEquip", startArgs); - this.shouldSendStart = false; - } - this.waitForTriggerRelease = false; - if (this.secondaryReleased() && this.equipedWithSecondary) { - this.equipedWithSecondary = false; - } - } - - if (dropDetected && this.prevDropDetected !== dropDetected) { - this.waitForTriggerRelease = true; - } - - // highlight the grabbed hotspot when the dropGesture is detected. - if (dropDetected && this.grabbedHotspot) { - equipHotspotBuddy.updateHotspot(this.grabbedHotspot, timestamp); - equipHotspotBuddy.highlightHotspot(this.grabbedHotspot); - } - - if (dropDetected && !this.waitForTriggerRelease && this.triggerSmoothedGrab()) { - this.waitForTriggerRelease = true; - // store the offset attach points into preferences. - this.endEquipEntity(); - return makeRunningValues(false, [], []); - } - this.prevDropDetected = dropDetected; - - equipHotspotBuddy.update(deltaTime, timestamp, controllerData); - - if (!this.shouldSendStart) { - var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; - Entities.callEntityMethod(this.targetEntityID, "continueEquip", args); - } - - return makeRunningValues(true, [this.targetEntityID], []); - }; - - this.storeAttachPointInSettings = function() { - if (this.grabbedHotspot && this.targetEntityID) { - var prefProps = Entities.getEntityProperties(this.targetEntityID, ["localPosition", "localRotation"]); - if (prefProps && prefProps.localPosition && prefProps.localRotation) { - storeAttachPointForHotspotInSettings(this.grabbedHotspot, this.hand, - prefProps.localPosition, prefProps.localRotation); - } - } - }; - - this.cleanup = function () { - if (this.targetEntityID) { - this.endEquipEntity(); - } - }; - } - - var handleMessage = function(channel, message, sender) { - var data; - if (sender === MyAvatar.sessionUUID) { - if (channel === 'Hifi-Hand-Grab') { - try { - data = JSON.parse(message); - var equipModule = (data.hand === "left") ? leftEquipEntity : rightEquipEntity; - var entityProperties = Entities.getEntityProperties(data.entityID, DISPATCHER_PROPERTIES); - entityProperties.id = data.entityID; - equipModule.setMessageGrabData(entityProperties); - } catch (e) { - print("WARNING: equipEntity.js -- error parsing Hifi-Hand-Grab message: " + message); - } - } else if (channel === 'Hifi-Hand-Drop') { - if (message === "left") { - leftEquipEntity.endEquipEntity(); - } else if (message === "right") { - rightEquipEntity.endEquipEntity(); - } else if (message === "both") { - leftEquipEntity.endEquipEntity(); - rightEquipEntity.endEquipEntity(); - } - } - } - }; - - var clearGrabActions = function(entityID) { - var actionIDs = Entities.getActionIDs(entityID); - var myGrabTag = "grab-" + MyAvatar.sessionUUID; - for (var actionIndex = 0; actionIndex < actionIDs.length; actionIndex++) { - var actionID = actionIDs[actionIndex]; - var actionArguments = Entities.getActionArguments(entityID, actionID); - var tag = actionArguments.tag; - if (tag === myGrabTag) { - Entities.deleteAction(entityID, actionID); - } - } - }; - - var onMousePress = function(event) { - if (isInEditMode() || !event.isLeftButton) { // don't consider any left clicks on the entity while in edit - return; - } - var pickRay = Camera.computePickRay(event.x, event.y); - var intersection = Entities.findRayIntersection(pickRay, true); - if (intersection.intersects) { - var entityID = intersection.entityID; - var entityProperties = Entities.getEntityProperties(entityID, DISPATCHER_PROPERTIES); - entityProperties.id = entityID; - var hasEquipData = getWearableData(entityProperties); - if (hasEquipData && entityIsEquippable(entityProperties)) { - entityProperties.id = entityID; - var rightHandPosition = MyAvatar.getJointPosition("RightHand"); - var leftHandPosition = MyAvatar.getJointPosition("LeftHand"); - var distanceToRightHand = Vec3.distance(entityProperties.position, rightHandPosition); - var distanceToLeftHand = Vec3.distance(entityProperties.position, leftHandPosition); - var leftHandAvailable = leftEquipEntity.targetEntityID === null; - var rightHandAvailable = rightEquipEntity.targetEntityID === null; - if (rightHandAvailable && (distanceToRightHand < distanceToLeftHand || !leftHandAvailable)) { - // clear any existing grab actions on the entity now (their later removal could affect bootstrapping flags) - clearGrabActions(entityID); - rightEquipEntity.setMessageGrabData(entityProperties); - } else if (leftHandAvailable && (distanceToLeftHand < distanceToRightHand || !rightHandAvailable)) { - // clear any existing grab actions on the entity now (their later removal could affect bootstrapping flags) - clearGrabActions(entityID); - leftEquipEntity.setMessageGrabData(entityProperties); - } - } - } - }; - - var onKeyPress = function(event) { - if (event.text.toLowerCase() === UNEQUIP_KEY) { - if (rightEquipEntity.targetEntityID) { - rightEquipEntity.endEquipEntity(); - } - if (leftEquipEntity.targetEntityID) { - leftEquipEntity.endEquipEntity(); - } - } - }; - - var deleteEntity = function(entityID) { - if (rightEquipEntity.targetEntityID === entityID) { - rightEquipEntity.endEquipEntity(); - } - if (leftEquipEntity.targetEntityID === entityID) { - leftEquipEntity.endEquipEntity(); - } - }; - - var clearEntities = function() { - if (rightEquipEntity.targetEntityID) { - rightEquipEntity.endEquipEntity(); - } - if (leftEquipEntity.targetEntityID) { - leftEquipEntity.endEquipEntity(); - } - }; - - Messages.subscribe('Hifi-Hand-Grab'); - Messages.subscribe('Hifi-Hand-Drop'); - Messages.messageReceived.connect(handleMessage); - Controller.mousePressEvent.connect(onMousePress); - Controller.keyPressEvent.connect(onKeyPress); - Entities.deletingEntity.connect(deleteEntity); - Entities.clearingEntities.connect(clearEntities); - - var leftEquipEntity = new EquipEntity(LEFT_HAND); - var rightEquipEntity = new EquipEntity(RIGHT_HAND); - - enableDispatcherModule("LeftEquipEntity", leftEquipEntity); - enableDispatcherModule("RightEquipEntity", rightEquipEntity); - - function cleanup() { - leftEquipEntity.cleanup(); - rightEquipEntity.cleanup(); - disableDispatcherModule("LeftEquipEntity"); - disableDispatcherModule("RightEquipEntity"); - clearAttachPoints(); - Messages.messageReceived.disconnect(handleMessage); - Controller.mousePressEvent.disconnect(onMousePress); - Controller.keyPressEvent.disconnect(onKeyPress); - Entities.deletingEntity.disconnect(deleteEntity); - Entities.clearingEntities.disconnect(clearEntities); - } - Script.scriptEnding.connect(cleanup); -}()); diff --git a/scripts/simplifiedUI/system/controllers/controllerModules/farActionGrabEntity.js b/scripts/simplifiedUI/system/controllers/controllerModules/farActionGrabEntity.js deleted file mode 100644 index 1eaed44ce2..0000000000 --- a/scripts/simplifiedUI/system/controllers/controllerModules/farActionGrabEntity.js +++ /dev/null @@ -1,591 +0,0 @@ -"use strict"; - -// farActionGrabEntity.js -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - -/* jslint bitwise: true */ - -/* global Script, Controller, RIGHT_HAND, LEFT_HAND, Mat4, MyAvatar, Vec3, Camera, Quat, - getEnabledModuleByName, makeRunningValues, Entities, - enableDispatcherModule, disableDispatcherModule, entityIsDistanceGrabbable, entityIsGrabbable, - makeDispatcherModuleParameters, MSECS_PER_SEC, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, - TRIGGER_OFF_VALUE, TRIGGER_ON_VALUE, ZERO_VEC, ensureDynamic, - getControllerWorldLocation, projectOntoEntityXYPlane, ContextOverlay, HMD, - Picks, makeLaserLockInfo, makeLaserParams, AddressManager, getEntityParents, Selection, DISPATCHER_HOVERING_LIST, - worldPositionToRegistrationFrameMatrix, DISPATCHER_PROPERTIES, Uuid, Picks -*/ - -Script.include("/~/system/libraries/controllerDispatcherUtils.js"); -Script.include("/~/system/libraries/controllers.js"); - -(function() { - - var MARGIN = 25; - - function TargetObject(entityID, entityProps) { - this.entityID = entityID; - this.entityProps = entityProps; - this.targetEntityID = null; - this.targetEntityProps = null; - this.previousCollisionStatus = null; - this.madeDynamic = null; - - this.makeDynamic = function() { - if (this.targetEntityID) { - var newProps = { - dynamic: true, - collisionless: true - }; - this.previousCollisionStatus = this.targetEntityProps.collisionless; - Entities.editEntity(this.targetEntityID, newProps); - this.madeDynamic = true; - } - }; - - this.restoreTargetEntityOriginalProps = function() { - if (this.madeDynamic) { - var props = {}; - props.dynamic = false; - props.collisionless = this.previousCollisionStatus; - var zeroVector = {x: 0, y: 0, z:0}; - props.localVelocity = zeroVector; - props.localRotation = zeroVector; - Entities.editEntity(this.targetEntityID, props); - } - }; - - this.getTargetEntity = function() { - var parentPropsLength = this.parentProps.length; - if (parentPropsLength !== 0) { - var targetEntity = { - id: this.parentProps[parentPropsLength - 1].id, - props: this.parentProps[parentPropsLength - 1]}; - this.targetEntityID = targetEntity.id; - this.targetEntityProps = targetEntity.props; - return targetEntity; - } - this.targetEntityID = this.entityID; - this.targetEntityProps = this.entityProps; - return { - id: this.entityID, - props: this.entityProps}; - }; - } - - function FarActionGrabEntity(hand) { - this.hand = hand; - this.grabbedThingID = null; - this.targetObject = null; - this.actionID = null; // action this script created... - this.entityToLockOnto = null; - this.potentialEntityWithContextOverlay = false; - this.entityWithContextOverlay = false; - this.contextOverlayTimer = false; - this.locked = false; - this.reticleMinX = MARGIN; - this.reticleMaxX = null; - this.reticleMinY = MARGIN; - this.reticleMaxY = null; - - this.ignoredEntities = []; - - var ACTION_TTL = 15; // seconds - - var DISTANCE_HOLDING_RADIUS_FACTOR = 3.5; // multiplied by distance between hand and object - var DISTANCE_HOLDING_ACTION_TIMEFRAME = 0.1; // how quickly objects move to their new position - var DISTANCE_HOLDING_UNITY_MASS = 1200; // The mass at which the distance holding action timeframe is unmodified - var DISTANCE_HOLDING_UNITY_DISTANCE = 6; // The distance at which the distance holding action timeframe is unmodified - - this.parameters = makeDispatcherModuleParameters( - 550, - this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"], - [], - 100, - makeLaserParams(this.hand, false)); - - - this.handToController = function() { - return (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand; - }; - - this.distanceGrabTimescale = function(mass, distance) { - var timeScale = DISTANCE_HOLDING_ACTION_TIMEFRAME * mass / - DISTANCE_HOLDING_UNITY_MASS * distance / - DISTANCE_HOLDING_UNITY_DISTANCE; - if (timeScale < DISTANCE_HOLDING_ACTION_TIMEFRAME) { - timeScale = DISTANCE_HOLDING_ACTION_TIMEFRAME; - } - return timeScale; - }; - - this.getMass = function(dimensions, density) { - return (dimensions.x * dimensions.y * dimensions.z) * density; - }; - - this.startFarGrabAction = function (controllerData, grabbedProperties) { - var controllerLocation = controllerData.controllerLocations[this.hand]; - var worldControllerPosition = controllerLocation.position; - var worldControllerRotation = controllerLocation.orientation; - - // transform the position into room space - var worldToSensorMat = Mat4.inverse(MyAvatar.getSensorToWorldMatrix()); - var roomControllerPosition = Mat4.transformPoint(worldToSensorMat, worldControllerPosition); - - var now = Date.now(); - - // add the action and initialize some variables - this.currentObjectPosition = grabbedProperties.position; - this.currentObjectRotation = grabbedProperties.rotation; - this.currentObjectTime = now; - this.currentCameraOrientation = Camera.orientation; - - this.grabRadius = this.grabbedDistance; - this.grabRadialVelocity = 0.0; - - // offset between controller vector at the grab radius and the entity position - var targetPosition = Vec3.multiply(this.grabRadius, Quat.getUp(worldControllerRotation)); - targetPosition = Vec3.sum(targetPosition, worldControllerPosition); - this.offsetPosition = Vec3.subtract(this.currentObjectPosition, targetPosition); - - // compute a constant based on the initial conditions which we use below to exaggerate hand motion - // onto the held object - this.radiusScalar = Math.log(this.grabRadius + 1.0); - if (this.radiusScalar < 1.0) { - this.radiusScalar = 1.0; - } - - // compute the mass for the purpose of energy and how quickly to move object - this.mass = this.getMass(grabbedProperties.dimensions, grabbedProperties.density); - var distanceToObject = Vec3.length(Vec3.subtract(MyAvatar.position, grabbedProperties.position)); - var timeScale = this.distanceGrabTimescale(this.mass, distanceToObject); - this.linearTimeScale = timeScale; - this.actionID = Entities.addAction("far-grab", this.grabbedThingID, { - targetPosition: this.currentObjectPosition, - linearTimeScale: timeScale, - targetRotation: this.currentObjectRotation, - angularTimeScale: timeScale, - tag: "far-grab-" + MyAvatar.sessionUUID, - ttl: ACTION_TTL - }); - if (this.actionID === Uuid.NULL) { - this.actionID = null; - } - - if (this.actionID !== null) { - var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; - Entities.callEntityMethod(this.grabbedThingID, "startDistanceGrab", args); - } - - Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); - this.previousRoomControllerPosition = roomControllerPosition; - }; - - this.continueDistanceHolding = function(controllerData) { - var controllerLocation = controllerData.controllerLocations[this.hand]; - var worldControllerPosition = controllerLocation.position; - var worldControllerRotation = controllerLocation.orientation; - - // also transform the position into room space - var worldToSensorMat = Mat4.inverse(MyAvatar.getSensorToWorldMatrix()); - var roomControllerPosition = Mat4.transformPoint(worldToSensorMat, worldControllerPosition); - - var grabbedProperties = Entities.getEntityProperties(this.grabbedThingID, DISPATCHER_PROPERTIES); - var now = Date.now(); - var deltaObjectTime = (now - this.currentObjectTime) / MSECS_PER_SEC; // convert to seconds - this.currentObjectTime = now; - - // the action was set up when this.distanceHolding was called. update the targets. - var radius = Vec3.distance(this.currentObjectPosition, worldControllerPosition) * - this.radiusScalar * DISTANCE_HOLDING_RADIUS_FACTOR; - if (radius < 1.0) { - radius = 1.0; - } - - var roomHandDelta = Vec3.subtract(roomControllerPosition, this.previousRoomControllerPosition); - var worldHandDelta = Mat4.transformVector(MyAvatar.getSensorToWorldMatrix(), roomHandDelta); - var handMoved = Vec3.multiply(worldHandDelta, radius); - this.currentObjectPosition = Vec3.sum(this.currentObjectPosition, handMoved); - - var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; - Entities.callEntityMethod(this.grabbedThingID, "continueDistanceGrab", args); - - // Update radialVelocity - var lastVelocity = Vec3.multiply(worldHandDelta, 1.0 / deltaObjectTime); - var delta = Vec3.normalize(Vec3.subtract(grabbedProperties.position, worldControllerPosition)); - var newRadialVelocity = Vec3.dot(lastVelocity, delta); - - var VELOCITY_AVERAGING_TIME = 0.016; - var blendFactor = deltaObjectTime / VELOCITY_AVERAGING_TIME; - if (blendFactor < 0.0) { - blendFactor = 0.0; - } else if (blendFactor > 1.0) { - blendFactor = 1.0; - } - this.grabRadialVelocity = blendFactor * newRadialVelocity + (1.0 - blendFactor) * this.grabRadialVelocity; - - var RADIAL_GRAB_AMPLIFIER = 10.0; - if (Math.abs(this.grabRadialVelocity) > 0.0) { - this.grabRadius = this.grabRadius + (this.grabRadialVelocity * deltaObjectTime * - this.grabRadius * RADIAL_GRAB_AMPLIFIER); - } - - // don't let grabRadius go all the way to zero, because it can't come back from that - var MINIMUM_GRAB_RADIUS = 0.1; - if (this.grabRadius < MINIMUM_GRAB_RADIUS) { - this.grabRadius = MINIMUM_GRAB_RADIUS; - } - var newTargetPosition = Vec3.multiply(this.grabRadius, Quat.getUp(worldControllerRotation)); - newTargetPosition = Vec3.sum(newTargetPosition, worldControllerPosition); - newTargetPosition = Vec3.sum(newTargetPosition, this.offsetPosition); - - // XXX - // this.maybeScale(grabbedProperties); - - var distanceToObject = Vec3.length(Vec3.subtract(MyAvatar.position, this.currentObjectPosition)); - - this.linearTimeScale = (this.linearTimeScale / 2); - if (this.linearTimeScale <= DISTANCE_HOLDING_ACTION_TIMEFRAME) { - this.linearTimeScale = DISTANCE_HOLDING_ACTION_TIMEFRAME; - } - var success = Entities.updateAction(this.grabbedThingID, this.actionID, { - targetPosition: newTargetPosition, - linearTimeScale: this.linearTimeScale, - targetRotation: this.currentObjectRotation, - angularTimeScale: this.distanceGrabTimescale(this.mass, distanceToObject), - ttl: ACTION_TTL - }); - if (!success) { - print("continueDistanceHolding -- updateAction failed: " + this.actionID); - this.actionID = null; - } - - this.previousRoomControllerPosition = roomControllerPosition; - }; - - this.endFarGrabAction = function () { - ensureDynamic(this.grabbedThingID); - this.distanceHolding = false; - this.distanceRotating = false; - Entities.deleteAction(this.grabbedThingID, this.actionID); - - var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; - Entities.callEntityMethod(this.grabbedThingID, "releaseGrab", args); - if (this.targetObject) { - this.targetObject.restoreTargetEntityOriginalProps(); - } - this.actionID = null; - this.grabbedThingID = null; - this.targetObject = null; - this.potentialEntityWithContextOverlay = false; - }; - - this.updateRecommendedArea = function() { - var dims = Controller.getViewportDimensions(); - this.reticleMaxX = dims.x - MARGIN; - this.reticleMaxY = dims.y - MARGIN; - }; - - this.calculateNewReticlePosition = function(intersection) { - this.updateRecommendedArea(); - var point2d = HMD.overlayFromWorldPoint(intersection); - point2d.x = Math.max(this.reticleMinX, Math.min(point2d.x, this.reticleMaxX)); - point2d.y = Math.max(this.reticleMinY, Math.min(point2d.y, this.reticleMaxY)); - return point2d; - }; - - this.restoreIgnoredEntities = function() { - for (var i = 0; i < this.ignoredEntities.length; i++) { - var data = { - action: 'remove', - id: this.ignoredEntities[i] - }; - Messages.sendMessage('Hifi-Hand-RayPick-Blacklist', JSON.stringify(data)); - } - this.ignoredEntities = []; - }; - - this.notPointingAtEntity = function(controllerData) { - var intersection = controllerData.rayPicks[this.hand]; - var entityProperty = Entities.getEntityProperties(intersection.objectID, DISPATCHER_PROPERTIES); - var entityType = entityProperty.type; - var hudRayPick = controllerData.hudRayPicks[this.hand]; - var point2d = this.calculateNewReticlePosition(hudRayPick.intersection); - if ((intersection.type === Picks.INTERSECTED_ENTITY && entityType === "Web") || - intersection.type === Picks.INTERSECTED_OVERLAY || Window.isPointOnDesktopWindow(point2d)) { - return true; - } - return false; - }; - - this.distanceRotate = function(otherFarGrabModule) { - this.distanceRotating = true; - this.distanceHolding = false; - - var worldControllerRotation = getControllerWorldLocation(this.handToController(), true).orientation; - var controllerRotationDelta = - Quat.multiply(worldControllerRotation, Quat.inverse(this.previousWorldControllerRotation)); - // Rotate entity by twice the delta rotation. - controllerRotationDelta = Quat.multiply(controllerRotationDelta, controllerRotationDelta); - - // Perform the rotation in the translation controller's action update. - otherFarGrabModule.currentObjectRotation = Quat.multiply(controllerRotationDelta, - otherFarGrabModule.currentObjectRotation); - - this.previousWorldControllerRotation = worldControllerRotation; - }; - - this.prepareDistanceRotatingData = function(controllerData) { - var intersection = controllerData.rayPicks[this.hand]; - - var controllerLocation = getControllerWorldLocation(this.handToController(), true); - var worldControllerPosition = controllerLocation.position; - var worldControllerRotation = controllerLocation.orientation; - - var grabbedProperties = Entities.getEntityProperties(intersection.objectID, DISPATCHER_PROPERTIES); - this.currentObjectPosition = grabbedProperties.position; - this.grabRadius = intersection.distance; - - // Offset between controller vector at the grab radius and the entity position. - var targetPosition = Vec3.multiply(this.grabRadius, Quat.getUp(worldControllerRotation)); - targetPosition = Vec3.sum(targetPosition, worldControllerPosition); - this.offsetPosition = Vec3.subtract(this.currentObjectPosition, targetPosition); - - // Initial controller rotation. - this.previousWorldControllerRotation = worldControllerRotation; - }; - - this.destroyContextOverlay = function(controllerData) { - if (this.entityWithContextOverlay) { - ContextOverlay.destroyContextOverlay(this.entityWithContextOverlay); - this.entityWithContextOverlay = false; - this.potentialEntityWithContextOverlay = false; - } - }; - - this.targetIsNull = function() { - var properties = Entities.getEntityProperties(this.grabbedThingID, DISPATCHER_PROPERTIES); - if (Object.keys(properties).length === 0 && this.distanceHolding) { - return true; - } - return false; - }; - - this.isReady = function (controllerData) { - if (HMD.active) { - if (this.notPointingAtEntity(controllerData)) { - return makeRunningValues(false, [], []); - } - - this.distanceHolding = false; - this.distanceRotating = false; - - if (controllerData.triggerValues[this.hand] > TRIGGER_ON_VALUE) { - this.prepareDistanceRotatingData(controllerData); - return makeRunningValues(true, [], []); - } else { - this.destroyContextOverlay(); - return makeRunningValues(false, [], []); - } - } - return makeRunningValues(false, [], []); - }; - - this.run = function (controllerData) { - - var intersection = controllerData.rayPicks[this.hand]; - if (intersection.type === Picks.INTERSECTED_ENTITY && !Window.isPhysicsEnabled()) { - // add to ignored items. - if (this.ignoredEntities.indexOf(intersection.objectID) === -1) { - var data = { - action: 'add', - id: intersection.objectID - }; - Messages.sendMessage('Hifi-Hand-RayPick-Blacklist', JSON.stringify(data)); - this.ignoredEntities.push(intersection.objectID); - } - } - if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE || - (this.notPointingAtEntity(controllerData) && Window.isPhysicsEnabled()) || this.targetIsNull()) { - this.endFarGrabAction(); - this.restoreIgnoredEntities(); - return makeRunningValues(false, [], []); - } - this.intersectionDistance = controllerData.rayPicks[this.hand].distance; - - var otherModuleName =this.hand === RIGHT_HAND ? "LeftFarActionGrabEntity" : "RightFarActionGrabEntity"; - var otherFarGrabModule = getEnabledModuleByName(otherModuleName); - - // gather up the readiness of the near-grab modules - var nearGrabNames = [ - this.hand === RIGHT_HAND ? "RightScaleAvatar" : "LeftScaleAvatar", - this.hand === RIGHT_HAND ? "RightFarTriggerEntity" : "LeftFarTriggerEntity", - this.hand === RIGHT_HAND ? "RightNearActionGrabEntity" : "LeftNearActionGrabEntity", - this.hand === RIGHT_HAND ? "RightNearParentingGrabEntity" : "LeftNearParentingGrabEntity", - this.hand === RIGHT_HAND ? "RightNearParentingGrabOverlay" : "LeftNearParentingGrabOverlay", - this.hand === RIGHT_HAND ? "RightNearTabletHighlight" : "LeftNearTabletHighlight" - ]; - - var nearGrabReadiness = []; - for (var i = 0; i < nearGrabNames.length; i++) { - var nearGrabModule = getEnabledModuleByName(nearGrabNames[i]); - var ready = nearGrabModule ? nearGrabModule.isReady(controllerData) : makeRunningValues(false, [], []); - nearGrabReadiness.push(ready); - } - - if (this.actionID) { - // if we are doing a distance grab and the object or tablet gets close enough to the controller, - // stop the far-grab so the near-grab or equip can take over. - for (var k = 0; k < nearGrabReadiness.length; k++) { - if (nearGrabReadiness[k].active && (nearGrabReadiness[k].targets[0] === this.grabbedThingID || - HMD.tabletID && nearGrabReadiness[k].targets[0] === HMD.tabletID)) { - this.endFarGrabAction(); - this.restoreIgnoredEntities(); - return makeRunningValues(false, [], []); - } - } - - this.continueDistanceHolding(controllerData); - } else { - // if we are doing a distance search and this controller moves into a position - // where it could near-grab something, stop searching. - for (var j = 0; j < nearGrabReadiness.length; j++) { - if (nearGrabReadiness[j].active) { - this.endFarGrabAction(); - this.restoreIgnoredEntities(); - return makeRunningValues(false, [], []); - } - } - - var rayPickInfo = controllerData.rayPicks[this.hand]; - if (rayPickInfo.type === Picks.INTERSECTED_ENTITY) { - if (controllerData.triggerClicks[this.hand]) { - var entityID = rayPickInfo.objectID; - var targetProps = Entities.getEntityProperties(entityID, DISPATCHER_PROPERTIES); - if (targetProps.href !== "") { - AddressManager.handleLookupString(targetProps.href); - this.restoreIgnoredEntities(); - return makeRunningValues(false, [], []); - } - - this.targetObject = new TargetObject(entityID, targetProps); - this.targetObject.parentProps = getEntityParents(targetProps); - - if (this.contextOverlayTimer) { - Script.clearTimeout(this.contextOverlayTimer); - } - this.contextOverlayTimer = false; - if (entityID === this.entityWithContextOverlay) { - this.destroyContextOverlay(); - } else { - Selection.removeFromSelectedItemsList("contextOverlayHighlightList", "entity", entityID); - } - - var targetEntity = this.targetObject.getTargetEntity(); - entityID = targetEntity.id; - targetProps = targetEntity.props; - - if (entityIsGrabbable(targetProps) || entityIsGrabbable(this.targetObject.entityProps)) { - if (!entityIsDistanceGrabbable(targetProps)) { - this.targetObject.makeDynamic(); - } - - if (!this.distanceRotating) { - this.grabbedThingID = entityID; - this.grabbedDistance = rayPickInfo.distance; - } - - if (otherFarGrabModule.grabbedThingID === this.grabbedThingID && - otherFarGrabModule.distanceHolding) { - this.prepareDistanceRotatingData(controllerData); - this.distanceRotate(otherFarGrabModule); - } else { - this.distanceHolding = true; - this.distanceRotating = false; - this.startFarGrabAction(controllerData, targetProps); - } - } - } else if (!this.entityWithContextOverlay) { - var _this = this; - - if (_this.potentialEntityWithContextOverlay !== rayPickInfo.objectID) { - if (_this.contextOverlayTimer) { - Script.clearTimeout(_this.contextOverlayTimer); - } - _this.contextOverlayTimer = false; - _this.potentialEntityWithContextOverlay = rayPickInfo.objectID; - } - - if (!_this.contextOverlayTimer) { - _this.contextOverlayTimer = Script.setTimeout(function () { - if (!_this.entityWithContextOverlay && - _this.contextOverlayTimer && - _this.potentialEntityWithContextOverlay === rayPickInfo.objectID) { - var props = Entities.getEntityProperties(rayPickInfo.objectID, DISPATCHER_PROPERTIES); - var pointerEvent = { - type: "Move", - id: _this.hand + 1, // 0 is reserved for hardware mouse - pos2D: projectOntoEntityXYPlane(rayPickInfo.objectID, - rayPickInfo.intersection, props), - pos3D: rayPickInfo.intersection, - normal: rayPickInfo.surfaceNormal, - direction: Vec3.subtract(ZERO_VEC, rayPickInfo.surfaceNormal), - button: "Secondary" - }; - if (ContextOverlay.createOrDestroyContextOverlay(rayPickInfo.objectID, pointerEvent)) { - _this.entityWithContextOverlay = rayPickInfo.objectID; - } - } - _this.contextOverlayTimer = false; - }, 500); - } - } - } else if (this.distanceRotating) { - this.distanceRotate(otherFarGrabModule); - } - } - return this.exitIfDisabled(controllerData); - }; - - this.exitIfDisabled = function(controllerData) { - var moduleName = this.hand === RIGHT_HAND ? "RightDisableModules" : "LeftDisableModules"; - var disableModule = getEnabledModuleByName(moduleName); - if (disableModule) { - if (disableModule.disableModules) { - this.endFarGrabAction(); - Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity", - this.highlightedEntity); - this.highlightedEntity = null; - this.restoreIgnoredEntities(); - return makeRunningValues(false, [], []); - } - } - var grabbedThing = (this.distanceHolding || this.distanceRotating) ? this.targetObject.entityID : null; - var offset = this.calculateOffset(controllerData); - var laserLockInfo = makeLaserLockInfo(grabbedThing, false, this.hand, offset); - return makeRunningValues(true, [], [], laserLockInfo); - }; - - this.calculateOffset = function(controllerData) { - if (this.distanceHolding || this.distanceRotating) { - var targetProps = Entities.getEntityProperties(this.targetObject.entityID, - [ "position", "rotation", "registrationPoint", "dimensions" ]); - return worldPositionToRegistrationFrameMatrix(targetProps, controllerData.rayPicks[this.hand].intersection); - } - return undefined; - }; - } - - var leftFarActionGrabEntity = new FarActionGrabEntity(LEFT_HAND); - var rightFarActionGrabEntity = new FarActionGrabEntity(RIGHT_HAND); - - enableDispatcherModule("LeftFarActionGrabEntity", leftFarActionGrabEntity); - enableDispatcherModule("RightFarActionGrabEntity", rightFarActionGrabEntity); - - function cleanup() { - disableDispatcherModule("LeftFarActionGrabEntity"); - disableDispatcherModule("RightFarActionGrabEntity"); - } - Script.scriptEnding.connect(cleanup); -}()); diff --git a/scripts/simplifiedUI/system/controllers/controllerModules/farGrabEntity.js b/scripts/simplifiedUI/system/controllers/controllerModules/farGrabEntity.js deleted file mode 100644 index ecafa3cb26..0000000000 --- a/scripts/simplifiedUI/system/controllers/controllerModules/farGrabEntity.js +++ /dev/null @@ -1,585 +0,0 @@ -"use strict"; - -// farGrabEntity.js -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - -/* jslint bitwise: true */ - -/* global Script, Controller, RIGHT_HAND, LEFT_HAND, Mat4, MyAvatar, Vec3, Quat, getEnabledModuleByName, makeRunningValues, - Entities, enableDispatcherModule, disableDispatcherModule, entityIsGrabbable, makeDispatcherModuleParameters, MSECS_PER_SEC, - HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, TRIGGER_OFF_VALUE, TRIGGER_ON_VALUE, ZERO_VEC, - projectOntoEntityXYPlane, ContextOverlay, HMD, Picks, makeLaserLockInfo, makeLaserParams, AddressManager, - getEntityParents, Selection, DISPATCHER_HOVERING_LIST, unhighlightTargetEntity, Messages, findGrabbableGroupParent, - worldPositionToRegistrationFrameMatrix, DISPATCHER_PROPERTIES -*/ - -Script.include("/~/system/libraries/controllerDispatcherUtils.js"); -Script.include("/~/system/libraries/controllers.js"); - -(function () { - var MARGIN = 25; - - function TargetObject(entityID, entityProps) { - this.entityID = entityID; - this.entityProps = entityProps; - this.targetEntityID = null; - this.targetEntityProps = null; - - this.getTargetEntity = function () { - var parentPropsLength = this.parentProps.length; - if (parentPropsLength !== 0) { - var targetEntity = { - id: this.parentProps[parentPropsLength - 1].id, - props: this.parentProps[parentPropsLength - 1] - }; - this.targetEntityID = targetEntity.id; - this.targetEntityProps = targetEntity.props; - return targetEntity; - } - this.targetEntityID = this.entityID; - this.targetEntityProps = this.entityProps; - return { - id: this.entityID, - props: this.entityProps - }; - }; - } - - function FarGrabEntity(hand) { - this.hand = hand; - this.grabbing = false; - this.targetEntityID = null; - this.targetObject = null; - this.previouslyUnhooked = {}; - this.potentialEntityWithContextOverlay = false; - this.entityWithContextOverlay = false; - this.contextOverlayTimer = false; - this.reticleMinX = MARGIN; - this.reticleMaxX = 0; - this.reticleMinY = MARGIN; - this.reticleMaxY = 0; - this.endedGrab = 0; - this.MIN_HAPTIC_PULSE_INTERVAL = 500; // ms - this.disabled = false; - var _this = this; - this.initialControllerRotation = Quat.IDENTITY; - this.currentControllerRotation = Quat.IDENTITY; - this.manipulating = false; - this.wasManipulating = false; - - var FAR_GRAB_JOINTS = [65527, 65528]; // FARGRAB_LEFTHAND_INDEX, FARGRAB_RIGHTHAND_INDEX - - var DISTANCE_HOLDING_RADIUS_FACTOR = 3.5; // multiplied by distance between hand and object - var DISTANCE_HOLDING_ACTION_TIMEFRAME = 0.1; // how quickly objects move to their new position - var DISTANCE_HOLDING_UNITY_MASS = 1200; // The mass at which the distance holding action timeframe is unmodified - var DISTANCE_HOLDING_UNITY_DISTANCE = 6; // The distance at which the distance holding action timeframe is unmodified - - this.parameters = makeDispatcherModuleParameters( - 540, - this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"], - [], - 100, - makeLaserParams(this.hand, false)); - - this.getOtherModule = function () { - return getEnabledModuleByName(this.hand === RIGHT_HAND ? ("LeftFarGrabEntity") : ("RightFarGrabEntity")); - }; - - // Get the rotation of the fargrabbed entity. - this.getTargetRotation = function () { - if (this.targetIsNull()) { - return null; - } else { - var props = Entities.getEntityProperties(this.targetEntityID, ["rotation"]); - return props.rotation; - } - }; - - this.getOffhand = function () { - return (this.hand === RIGHT_HAND ? LEFT_HAND : RIGHT_HAND); - } - - // Activation criteria for rotating a fargrabbed entity. If we're changing the mapping, this is where to do it. - this.shouldManipulateTarget = function (controllerData) { - return (controllerData.triggerValues[this.getOffhand()] > TRIGGER_ON_VALUE || controllerData.secondaryValues[this.getOffhand()] > TRIGGER_ON_VALUE) ? true : false; - }; - - // Get the delta between the current rotation and where the controller was when manipulation started. - this.calculateEntityRotationManipulation = function (controllerRotation) { - return Quat.multiply(controllerRotation, Quat.inverse(this.initialControllerRotation)); - }; - - this.setJointTranslation = function (newTargetPosLocal) { - MyAvatar.setJointTranslation(FAR_GRAB_JOINTS[this.hand], newTargetPosLocal); - }; - - this.setJointRotation = function (newTargetRotLocal) { - MyAvatar.setJointRotation(FAR_GRAB_JOINTS[this.hand], newTargetRotLocal); - }; - - this.setJointRotation = function (newTargetRotLocal) { - MyAvatar.setJointRotation(FAR_GRAB_JOINTS[this.hand], newTargetRotLocal); - }; - - this.handToController = function () { - return (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand; - }; - - this.distanceGrabTimescale = function (mass, distance) { - var timeScale = DISTANCE_HOLDING_ACTION_TIMEFRAME * mass / - DISTANCE_HOLDING_UNITY_MASS * distance / - DISTANCE_HOLDING_UNITY_DISTANCE; - if (timeScale < DISTANCE_HOLDING_ACTION_TIMEFRAME) { - timeScale = DISTANCE_HOLDING_ACTION_TIMEFRAME; - } - return timeScale; - }; - - this.getMass = function (dimensions, density) { - return (dimensions.x * dimensions.y * dimensions.z) * density; - }; - - this.startFarGrabEntity = function (controllerData, targetProps) { - var controllerLocation = controllerData.controllerLocations[this.hand]; - var worldControllerPosition = controllerLocation.position; - var worldControllerRotation = controllerLocation.orientation; - // transform the position into room space - var worldToSensorMat = Mat4.inverse(MyAvatar.getSensorToWorldMatrix()); - var roomControllerPosition = Mat4.transformPoint(worldToSensorMat, worldControllerPosition); - - var now = Date.now(); - - // add the action and initialize some variables - this.currentObjectPosition = targetProps.position; - this.currentObjectRotation = targetProps.rotation; - this.currentObjectTime = now; - - this.grabRadius = this.grabbedDistance; - this.grabRadialVelocity = 0.0; - - // offset between controller vector at the grab radius and the entity position - var targetPosition = Vec3.multiply(this.grabRadius, Quat.getUp(worldControllerRotation)); - targetPosition = Vec3.sum(targetPosition, worldControllerPosition); - this.offsetPosition = Vec3.subtract(this.currentObjectPosition, targetPosition); - - // compute a constant based on the initial conditions which we use below to exaggerate hand motion - // onto the held object - this.radiusScalar = Math.log(this.grabRadius + 1.0); - if (this.radiusScalar < 1.0) { - this.radiusScalar = 1.0; - } - - // compute the mass for the purpose of energy and how quickly to move object - this.mass = this.getMass(targetProps.dimensions, targetProps.density); - - // Debounce haptic pules. Can occur as near grab controller module vacillates between being ready or not due to - // changing positions and floating point rounding. - if (Date.now() - this.endedGrab > this.MIN_HAPTIC_PULSE_INTERVAL) { - Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); - } - - unhighlightTargetEntity(this.targetEntityID); - var message = { - hand: this.hand, - entityID: this.targetEntityID - }; - - Messages.sendLocalMessage('Hifi-unhighlight-entity', JSON.stringify(message)); - - var newTargetPosLocal = MyAvatar.worldToJointPoint(targetProps.position); - var newTargetRotLocal = targetProps.rotation; - this.setJointTranslation(newTargetPosLocal); - this.setJointRotation(newTargetRotLocal); - - var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; - Entities.callEntityMethod(targetProps.id, "startDistanceGrab", args); - - this.targetEntityID = targetProps.id; - - - if (this.grabID) { - MyAvatar.releaseGrab(this.grabID); - } - var farJointIndex = FAR_GRAB_JOINTS[this.hand]; - this.grabID = MyAvatar.grab(targetProps.id, farJointIndex, - Entities.worldToLocalPosition(targetProps.position, MyAvatar.SELF_ID, farJointIndex), - Entities.worldToLocalRotation(targetProps.rotation, MyAvatar.SELF_ID, farJointIndex)); - - Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({ - action: 'grab', - grabbedEntity: targetProps.id, - joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand" - })); - this.grabbing = true; - - this.previousRoomControllerPosition = roomControllerPosition; - }; - - this.continueDistanceHolding = function (controllerData) { - var controllerLocation = controllerData.controllerLocations[this.hand]; - var worldControllerPosition = controllerLocation.position; - var worldControllerRotation = controllerLocation.orientation; - - // also transform the position into room space - var worldToSensorMat = Mat4.inverse(MyAvatar.getSensorToWorldMatrix()); - var roomControllerPosition = Mat4.transformPoint(worldToSensorMat, worldControllerPosition); - - var targetProps = Entities.getEntityProperties(this.targetEntityID, DISPATCHER_PROPERTIES); - var now = Date.now(); - var deltaObjectTime = (now - this.currentObjectTime) / MSECS_PER_SEC; // convert to seconds - this.currentObjectTime = now; - - // the action was set up when this.distanceHolding was called. update the targets. - var radius = Vec3.distance(this.currentObjectPosition, worldControllerPosition) * - this.radiusScalar * DISTANCE_HOLDING_RADIUS_FACTOR; - if (radius < 1.0) { - radius = 1.0; - } - - var roomHandDelta = Vec3.subtract(roomControllerPosition, this.previousRoomControllerPosition); - var worldHandDelta = Mat4.transformVector(MyAvatar.getSensorToWorldMatrix(), roomHandDelta); - var handMoved = Vec3.multiply(worldHandDelta, radius); - this.currentObjectPosition = Vec3.sum(this.currentObjectPosition, handMoved); - - var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; - Entities.callEntityMethod(this.targetEntityID, "continueDistanceGrab", args); - - // Update radialVelocity - var lastVelocity = Vec3.multiply(worldHandDelta, 1.0 / deltaObjectTime); - var delta = Vec3.normalize(Vec3.subtract(targetProps.position, worldControllerPosition)); - var newRadialVelocity = Vec3.dot(lastVelocity, delta); - - var VELOCITY_AVERAGING_TIME = 0.016; - var blendFactor = deltaObjectTime / VELOCITY_AVERAGING_TIME; - if (blendFactor < 0.0) { - blendFactor = 0.0; - } else if (blendFactor > 1.0) { - blendFactor = 1.0; - } - this.grabRadialVelocity = blendFactor * newRadialVelocity + (1.0 - blendFactor) * this.grabRadialVelocity; - - var RADIAL_GRAB_AMPLIFIER = 10.0; - if (Math.abs(this.grabRadialVelocity) > 0.0) { - this.grabRadius = this.grabRadius + (this.grabRadialVelocity * deltaObjectTime * - this.grabRadius * RADIAL_GRAB_AMPLIFIER); - } - - // don't let grabRadius go all the way to zero, because it can't come back from that - var MINIMUM_GRAB_RADIUS = 0.1; - if (this.grabRadius < MINIMUM_GRAB_RADIUS) { - this.grabRadius = MINIMUM_GRAB_RADIUS; - } - var newTargetPosition = Vec3.multiply(this.grabRadius, Quat.getUp(worldControllerRotation)); - newTargetPosition = Vec3.sum(newTargetPosition, worldControllerPosition); - newTargetPosition = Vec3.sum(newTargetPosition, this.offsetPosition); - - var newTargetPosLocal = MyAvatar.worldToJointPoint(newTargetPosition); - - // This block handles the user's ability to rotate the object they're FarGrabbing - if (this.shouldManipulateTarget(controllerData)) { - // Get the pose of the controller that is not grabbing. - var pose = Controller.getPoseValue((this.getOffhand() ? Controller.Standard.RightHand : Controller.Standard.LeftHand)); - if (pose.valid) { - // If we weren't manipulating the object yet, initialize the entity's original position. - if (!this.manipulating) { - // This will only be triggered if we've let go of the off-hand trigger and pulled it again without ending a grab. - // Need to poll the entity's rotation again here. - if (!this.wasManipulating) { - this.initialEntityRotation = this.getTargetRotation(); - } - // Save the original controller orientation, we only care about the delta between this rotation and wherever - // the controller rotates, so that we can apply it to the entity's rotation. - this.initialControllerRotation = Quat.multiply(pose.rotation, MyAvatar.orientation); - this.manipulating = true; - } - } - - var rot = Quat.multiply(pose.rotation, MyAvatar.orientation); - var rotBetween = this.calculateEntityRotationManipulation(rot); - var doubleRot = Quat.multiply(rotBetween, rotBetween); - this.lastJointRotation = Quat.multiply(doubleRot, this.initialEntityRotation); - this.setJointRotation(this.lastJointRotation); - } else { - // If we were manipulating but the user isn't currently expressing this intent, we want to know so we preserve the rotation - // between manipulations without ending the fargrab. - if (this.manipulating) { - this.initialEntityRotation = this.lastJointRotation; - this.wasManipulating = true; - } - this.manipulating = false; - // Reset the inital controller position. - this.initialControllerRotation = Quat.IDENTITY; - } - this.setJointTranslation(newTargetPosLocal); - - this.previousRoomControllerPosition = roomControllerPosition; - }; - - this.endFarGrabEntity = function (controllerData) { - if (this.grabID) { - MyAvatar.releaseGrab(this.grabID); - this.grabID = null; - } - - this.endedGrab = Date.now(); - - var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; - Entities.callEntityMethod(this.targetEntityID, "releaseGrab", args); - Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({ - action: 'release', - grabbedEntity: this.targetEntityID, - joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand" - })); - unhighlightTargetEntity(this.targetEntityID); - this.grabbing = false; - this.potentialEntityWithContextOverlay = false; - MyAvatar.clearJointData(FAR_GRAB_JOINTS[this.hand]); - this.initialEntityRotation = Quat.IDENTITY; - this.initialControllerRotation = Quat.IDENTITY; - this.targetEntityID = null; - this.manipulating = false; - this.wasManipulating = false; - var otherModule = this.getOtherModule(); - otherModule.disabled = false; - }; - - this.updateRecommendedArea = function () { - var dims = Controller.getViewportDimensions(); - this.reticleMaxX = dims.x - MARGIN; - this.reticleMaxY = dims.y - MARGIN; - }; - - this.calculateNewReticlePosition = function (intersection) { - this.updateRecommendedArea(); - var point2d = HMD.overlayFromWorldPoint(intersection); - point2d.x = Math.max(this.reticleMinX, Math.min(point2d.x, this.reticleMaxX)); - point2d.y = Math.max(this.reticleMinY, Math.min(point2d.y, this.reticleMaxY)); - return point2d; - }; - - this.notPointingAtEntity = function (controllerData) { - var intersection = controllerData.rayPicks[this.hand]; - var entityProperty = Entities.getEntityProperties(intersection.objectID, DISPATCHER_PROPERTIES); - var entityType = entityProperty.type; - var hudRayPick = controllerData.hudRayPicks[this.hand]; - var point2d = this.calculateNewReticlePosition(hudRayPick.intersection); - if ((intersection.type === Picks.INTERSECTED_ENTITY && entityType === "Web") || - intersection.type === Picks.INTERSECTED_OVERLAY || Window.isPointOnDesktopWindow(point2d)) { - return true; - } - return false; - }; - - this.destroyContextOverlay = function (controllerData) { - if (this.entityWithContextOverlay) { - ContextOverlay.destroyContextOverlay(this.entityWithContextOverlay); - this.entityWithContextOverlay = false; - this.potentialEntityWithContextOverlay = false; - } - }; - - this.targetIsNull = function () { - var properties = Entities.getEntityProperties(this.targetEntityID, DISPATCHER_PROPERTIES); - if (Object.keys(properties).length === 0 && this.distanceHolding) { - return true; - } - return false; - }; - - this.getTargetProps = function (controllerData) { - var targetEntity = controllerData.rayPicks[this.hand].objectID; - if (targetEntity) { - var gtProps = Entities.getEntityProperties(targetEntity, DISPATCHER_PROPERTIES); - if (entityIsGrabbable(gtProps)) { - // if we've attempted to grab a child, roll up to the root of the tree - var groupRootProps = findGrabbableGroupParent(controllerData, gtProps); - if (entityIsGrabbable(groupRootProps)) { - return groupRootProps; - } - return gtProps; - } - } - return null; - }; - - this.isReady = function (controllerData) { - if (HMD.active) { - if (this.notPointingAtEntity(controllerData)) { - return makeRunningValues(false, [], []); - } - - this.distanceHolding = false; - - if (controllerData.triggerValues[this.hand] > TRIGGER_ON_VALUE && !this.disabled) { - var otherModule = this.getOtherModule(); - otherModule.disabled = true; - return makeRunningValues(true, [], []); - } else { - this.destroyContextOverlay(); - } - } - return makeRunningValues(false, [], []); - }; - - this.run = function (controllerData) { - if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE || this.targetIsNull()) { - this.endFarGrabEntity(controllerData); - return makeRunningValues(false, [], []); - } - this.intersectionDistance = controllerData.rayPicks[this.hand].distance; - - // gather up the readiness of the near-grab modules - var nearGrabNames = [ - this.hand === RIGHT_HAND ? "RightScaleAvatar" : "LeftScaleAvatar", - this.hand === RIGHT_HAND ? "RightFarTriggerEntity" : "LeftFarTriggerEntity", - this.hand === RIGHT_HAND ? "RightNearGrabEntity" : "LeftNearGrabEntity" - ]; - if (!this.grabbing) { - nearGrabNames.push(this.hand === RIGHT_HAND ? "RightNearParentingGrabOverlay" : "LeftNearParentingGrabOverlay"); - nearGrabNames.push(this.hand === RIGHT_HAND ? "RightNearTabletHighlight" : "LeftNearTabletHighlight"); - } - - var nearGrabReadiness = []; - for (var i = 0; i < nearGrabNames.length; i++) { - var nearGrabModule = getEnabledModuleByName(nearGrabNames[i]); - var ready = nearGrabModule ? nearGrabModule.isReady(controllerData) : makeRunningValues(false, [], []); - nearGrabReadiness.push(ready); - } - - if (this.targetEntityID) { - // if we are doing a distance grab and the object gets close enough to the controller, - // stop the far-grab so the near-grab or equip can take over. - for (var k = 0; k < nearGrabReadiness.length; k++) { - if (nearGrabReadiness[k].active && (nearGrabReadiness[k].targets[0] === this.targetEntityID)) { - this.endFarGrabEntity(controllerData); - return makeRunningValues(false, [], []); - } - } - - this.continueDistanceHolding(controllerData); - } else { - // if we are doing a distance search and this controller moves into a position - // where it could near-grab something, stop searching. - for (var j = 0; j < nearGrabReadiness.length; j++) { - if (nearGrabReadiness[j].active) { - this.endFarGrabEntity(controllerData); - return makeRunningValues(false, [], []); - } - } - - var rayPickInfo = controllerData.rayPicks[this.hand]; - if (rayPickInfo.type === Picks.INTERSECTED_ENTITY) { - if (controllerData.triggerClicks[this.hand]) { - var entityID = rayPickInfo.objectID; - var targetProps = Entities.getEntityProperties(entityID, DISPATCHER_PROPERTIES); - if (targetProps.href !== "") { - AddressManager.handleLookupString(targetProps.href); - return makeRunningValues(false, [], []); - } - - this.targetObject = new TargetObject(entityID, targetProps); - this.targetObject.parentProps = getEntityParents(targetProps); - - if (this.contextOverlayTimer) { - Script.clearTimeout(this.contextOverlayTimer); - } - this.contextOverlayTimer = false; - if (entityID === this.entityWithContextOverlay) { - this.destroyContextOverlay(); - } else { - Selection.removeFromSelectedItemsList("contextOverlayHighlightList", "entity", entityID); - } - - var targetEntity = this.targetObject.getTargetEntity(); - entityID = targetEntity.id; - targetProps = targetEntity.props; - - if (entityIsGrabbable(targetProps) || entityIsGrabbable(this.targetObject.entityProps)) { - - this.targetEntityID = entityID; - this.grabbedDistance = rayPickInfo.distance; - this.distanceHolding = true; - this.startFarGrabEntity(controllerData, targetProps); - } - } else if (!this.entityWithContextOverlay) { - var _this = this; - - if (_this.potentialEntityWithContextOverlay !== rayPickInfo.objectID) { - if (_this.contextOverlayTimer) { - Script.clearTimeout(_this.contextOverlayTimer); - } - _this.contextOverlayTimer = false; - _this.potentialEntityWithContextOverlay = rayPickInfo.objectID; - } - - if (!_this.contextOverlayTimer) { - _this.contextOverlayTimer = Script.setTimeout(function () { - if (!_this.entityWithContextOverlay && - _this.contextOverlayTimer && - _this.potentialEntityWithContextOverlay === rayPickInfo.objectID) { - var cotProps = Entities.getEntityProperties(rayPickInfo.objectID, - DISPATCHER_PROPERTIES); - var pointerEvent = { - type: "Move", - id: _this.hand + 1, // 0 is reserved for hardware mouse - pos2D: projectOntoEntityXYPlane(rayPickInfo.objectID, - rayPickInfo.intersection, cotProps), - pos3D: rayPickInfo.intersection, - normal: rayPickInfo.surfaceNormal, - direction: Vec3.subtract(ZERO_VEC, rayPickInfo.surfaceNormal), - button: "Secondary" - }; - if (ContextOverlay.createOrDestroyContextOverlay(rayPickInfo.objectID, pointerEvent)) { - _this.entityWithContextOverlay = rayPickInfo.objectID; - } - } - _this.contextOverlayTimer = false; - }, 500); - } - } - } - } - return this.exitIfDisabled(controllerData); - }; - - this.exitIfDisabled = function (controllerData) { - var moduleName = this.hand === RIGHT_HAND ? "RightDisableModules" : "LeftDisableModules"; - var disableModule = getEnabledModuleByName(moduleName); - if (disableModule) { - if (disableModule.disableModules) { - this.endFarGrabEntity(controllerData); - Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity", this.highlightedEntity); - this.highlightedEntity = null; - return makeRunningValues(false, [], []); - } - } - var grabbedThing = this.distanceHolding ? this.targetObject.entityID : null; - var offset = this.calculateOffset(controllerData); - var laserLockInfo = makeLaserLockInfo(grabbedThing, false, this.hand, offset); - return makeRunningValues(true, [], [], laserLockInfo); - }; - - this.calculateOffset = function (controllerData) { - if (this.distanceHolding) { - var targetProps = Entities.getEntityProperties(this.targetObject.entityID, - ["position", "rotation", "registrationPoint", "dimensions"]); - return worldPositionToRegistrationFrameMatrix(targetProps, controllerData.rayPicks[this.hand].intersection); - } - return undefined; - }; - } - - var leftFarGrabEntity = new FarGrabEntity(LEFT_HAND); - var rightFarGrabEntity = new FarGrabEntity(RIGHT_HAND); - - enableDispatcherModule("LeftFarGrabEntity", leftFarGrabEntity); - enableDispatcherModule("RightFarGrabEntity", rightFarGrabEntity); - - function cleanup() { - disableDispatcherModule("LeftFarGrabEntity"); - disableDispatcherModule("RightFarGrabEntity"); - } - Script.scriptEnding.connect(cleanup); -}()); diff --git a/scripts/simplifiedUI/system/controllers/controllerModules/farTrigger.js b/scripts/simplifiedUI/system/controllers/controllerModules/farTrigger.js deleted file mode 100644 index c9c9d3deee..0000000000 --- a/scripts/simplifiedUI/system/controllers/controllerModules/farTrigger.js +++ /dev/null @@ -1,102 +0,0 @@ -"use strict"; - -// farTrigger.js -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - - -/* global Script, RIGHT_HAND, LEFT_HAND, MyAvatar, - makeRunningValues, Entities, enableDispatcherModule, disableDispatcherModule, makeDispatcherModuleParameters, - getGrabbableData, makeLaserParams, DISPATCHER_PROPERTIES -*/ - -Script.include("/~/system/libraries/controllerDispatcherUtils.js"); -Script.include("/~/system/libraries/controllers.js"); - -(function() { - function entityWantsFarTrigger(props) { - var grabbableData = getGrabbableData(props); - return grabbableData.triggerable; - } - - function FarTriggerEntity(hand) { - this.hand = hand; - this.targetEntityID = null; - this.grabbing = false; - this.previousParentID = {}; - this.previousParentJointIndex = {}; - this.previouslyUnhooked = {}; - - this.parameters = makeDispatcherModuleParameters( - 520, - this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"], - [], - 100, - makeLaserParams(this.hand, false)); - - this.getTargetProps = function (controllerData) { - var targetEntity = controllerData.rayPicks[this.hand].objectID; - if (targetEntity && controllerData.rayPicks[this.hand].type === RayPick.INTERSECTED_ENTITY) { - var targetProperties = Entities.getEntityProperties(targetEntity, DISPATCHER_PROPERTIES); - if (entityWantsFarTrigger(targetProperties)) { - return targetProperties; - } - } - return null; - }; - - this.startFarTrigger = function (controllerData) { - var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; - Entities.callEntityMethod(this.targetEntityID, "startFarTrigger", args); - }; - - this.continueFarTrigger = function (controllerData) { - var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; - Entities.callEntityMethod(this.targetEntityID, "continueFarTrigger", args); - }; - - this.endFarTrigger = function (controllerData) { - var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; - Entities.callEntityMethod(this.targetEntityID, "stopFarTrigger", args); - }; - - this.isReady = function (controllerData) { - this.targetEntityID = null; - if (controllerData.triggerClicks[this.hand] === 0) { - return makeRunningValues(false, [], []); - } - - var targetProps = this.getTargetProps(controllerData); - if (targetProps) { - this.targetEntityID = targetProps.id; - this.startFarTrigger(controllerData); - return makeRunningValues(true, [this.targetEntityID], []); - } else { - return makeRunningValues(false, [], []); - } - }; - - this.run = function (controllerData) { - var targetEntity = controllerData.rayPicks[this.hand].objectID; - if (controllerData.triggerClicks[this.hand] === 0 || this.targetEntityID !== targetEntity) { - this.endFarTrigger(controllerData); - return makeRunningValues(false, [], []); - } - this.continueFarTrigger(controllerData); - return makeRunningValues(true, [this.targetEntityID], []); - }; - } - - var leftFarTriggerEntity = new FarTriggerEntity(LEFT_HAND); - var rightFarTriggerEntity = new FarTriggerEntity(RIGHT_HAND); - - enableDispatcherModule("LeftFarTriggerEntity", leftFarTriggerEntity); - enableDispatcherModule("RightFarTriggerEntity", rightFarTriggerEntity); - - function cleanup() { - disableDispatcherModule("LeftFarTriggerEntity"); - disableDispatcherModule("RightFarTriggerEntity"); - } - Script.scriptEnding.connect(cleanup); -}()); diff --git a/scripts/simplifiedUI/system/controllers/controllerModules/hudOverlayPointer.js b/scripts/simplifiedUI/system/controllers/controllerModules/hudOverlayPointer.js deleted file mode 100644 index f7d5b5a2dd..0000000000 --- a/scripts/simplifiedUI/system/controllers/controllerModules/hudOverlayPointer.js +++ /dev/null @@ -1,126 +0,0 @@ -// -// hudOverlayPointer.js -// -// scripts/system/controllers/controllerModules/ -// -// Created by Dante Ruiz 2017-9-21 -// 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 -// - -/* global Script, Controller, RIGHT_HAND, LEFT_HAND, HMD, makeLaserParams */ -(function() { - Script.include("/~/system/libraries/controllers.js"); - var ControllerDispatcherUtils = Script.require("/~/system/libraries/controllerDispatcherUtils.js"); - var MARGIN = 25; - var HUD_LASER_OFFSET = 2; - function HudOverlayPointer(hand) { - this.hand = hand; - this.running = false; - this.reticleMinX = MARGIN; - this.reticleMaxX; - this.reticleMinY = MARGIN; - this.reticleMaxY; - this.parameters = ControllerDispatcherUtils.makeDispatcherModuleParameters( - 160, // Same as webSurfaceLaserInput. - this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"], - [], - 100, - makeLaserParams((this.hand + HUD_LASER_OFFSET), false)); - - this.getFarGrab = function () { - return getEnabledModuleByName(this.hand === RIGHT_HAND ? ("RightFarGrabEntity") : ("LeftFarGrabEntity")); - } - - this.farGrabActive = function () { - var farGrab = this.getFarGrab(); - // farGrab will be null if module isn't loaded. - if (farGrab) { - return farGrab.targetIsNull(); - } else { - return false; - } - }; - - this.getOtherHandController = function() { - return (this.hand === RIGHT_HAND) ? Controller.Standard.LeftHand : Controller.Standard.RightHand; - }; - - this.handToController = function() { - return (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand; - }; - - this.updateRecommendedArea = function() { - var dims = Controller.getViewportDimensions(); - this.reticleMaxX = dims.x - MARGIN; - this.reticleMaxY = dims.y - MARGIN; - }; - - this.calculateNewReticlePosition = function(intersection) { - this.updateRecommendedArea(); - var point2d = HMD.overlayFromWorldPoint(intersection); - point2d.x = Math.max(this.reticleMinX, Math.min(point2d.x, this.reticleMaxX)); - point2d.y = Math.max(this.reticleMinY, Math.min(point2d.y, this.reticleMaxY)); - return point2d; - }; - - this.pointingAtTablet = function(controllerData) { - var rayPick = controllerData.rayPicks[this.hand]; - return (HMD.tabletScreenID && HMD.homeButtonID && (rayPick.objectID === HMD.tabletScreenID || rayPick.objectID === HMD.homeButtonID)); - }; - - this.getOtherModule = function() { - return this.hand === RIGHT_HAND ? leftHudOverlayPointer : rightHudOverlayPointer; - }; - - this.processLaser = function(controllerData) { - var controllerLocation = controllerData.controllerLocations[this.hand]; - if ((controllerData.triggerValues[this.hand] < ControllerDispatcherUtils.TRIGGER_ON_VALUE || !controllerLocation.valid) || - this.pointingAtTablet(controllerData)) { - return false; - } - var hudRayPick = controllerData.hudRayPicks[this.hand]; - var point2d = this.calculateNewReticlePosition(hudRayPick.intersection); - if (!Window.isPointOnDesktopWindow(point2d) && !this.triggerClicked) { - return false; - } - - this.triggerClicked = controllerData.triggerClicks[this.hand]; - return true; - }; - - this.isReady = function (controllerData) { - var otherModuleRunning = this.getOtherModule().running; - if (!otherModuleRunning && HMD.active && !this.farGrabActive()) { - if (this.processLaser(controllerData)) { - this.running = true; - return ControllerDispatcherUtils.makeRunningValues(true, [], []); - } else { - this.running = false; - return ControllerDispatcherUtils.makeRunningValues(false, [], []); - } - } - return ControllerDispatcherUtils.makeRunningValues(false, [], []); - }; - - this.run = function (controllerData, deltaTime) { - return this.isReady(controllerData); - }; - } - - - var leftHudOverlayPointer = new HudOverlayPointer(LEFT_HAND); - var rightHudOverlayPointer = new HudOverlayPointer(RIGHT_HAND); - - ControllerDispatcherUtils.enableDispatcherModule("LeftHudOverlayPointer", leftHudOverlayPointer); - ControllerDispatcherUtils.enableDispatcherModule("RightHudOverlayPointer", rightHudOverlayPointer); - - function cleanup() { - ControllerDispatcherUtils.disableDispatcherModule("LeftHudOverlayPointer"); - ControllerDispatcherUtils.disableDispatcherModule("RightHudOverlayPointer"); - } - Script.scriptEnding.connect(cleanup); - -})(); diff --git a/scripts/simplifiedUI/system/controllers/controllerModules/inEditMode.js b/scripts/simplifiedUI/system/controllers/controllerModules/inEditMode.js deleted file mode 100644 index 5709b19efe..0000000000 --- a/scripts/simplifiedUI/system/controllers/controllerModules/inEditMode.js +++ /dev/null @@ -1,253 +0,0 @@ -"use strict"; - -// inEditMode.js -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - -/* jslint bitwise: true */ - -/* global Script, Controller, RIGHT_HAND, LEFT_HAND, enableDispatcherModule, disableDispatcherModule, makeRunningValues, - Messages, makeDispatcherModuleParameters, HMD, getEnabledModuleByName, TRIGGER_ON_VALUE, isInEditMode, Picks, - makeLaserParams -*/ - -Script.include("/~/system/libraries/controllerDispatcherUtils.js"); -Script.include("/~/system/libraries/controllers.js"); -Script.include("/~/system/libraries/utils.js"); - -(function () { - var MARGIN = 25; - function InEditMode(hand) { - this.hand = hand; - this.isEditing = false; - this.triggerClicked = false; - this.selectedTarget = null; - this.reticleMinX = MARGIN; - this.reticleMaxX = null; - this.reticleMinY = MARGIN; - this.reticleMaxY = null; - - this.parameters = makeDispatcherModuleParameters( - 165, // Lower priority than webSurfaceLaserInput and hudOverlayPointer. - this.hand === RIGHT_HAND ? ["rightHand", "rightHandEquip", "rightHandTrigger"] : ["leftHand", "leftHandEquip", "leftHandTrigger"], - [], - 100, - makeLaserParams(this.hand, false)); - - this.nearTablet = function(overlays) { - for (var i = 0; i < overlays.length; i++) { - if (HMD.tabletID && overlays[i] === HMD.tabletID) { - return true; - } - } - return false; - }; - - this.handToController = function() { - return (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand; - }; - - this.pointingAtTablet = function(objectID) { - return (HMD.tabletScreenID && objectID === HMD.tabletScreenID) || - (HMD.homeButtonID && objectID === HMD.homeButtonID); - }; - - this.calculateNewReticlePosition = function(intersection) { - var dims = Controller.getViewportDimensions(); - this.reticleMaxX = dims.x - MARGIN; - this.reticleMaxY = dims.y - MARGIN; - var point2d = HMD.overlayFromWorldPoint(intersection); - point2d.x = Math.max(this.reticleMinX, Math.min(point2d.x, this.reticleMaxX)); - point2d.y = Math.max(this.reticleMinY, Math.min(point2d.y, this.reticleMaxY)); - return point2d; - }; - - this.ENTITY_TOOL_UPDATES_CHANNEL = "entityToolUpdates"; - - this.sendPickData = function(controllerData) { - if (controllerData.triggerClicks[this.hand]) { - var hand = this.hand === RIGHT_HAND ? Controller.Standard.RightHand : Controller.Standard.LeftHand; - if (!this.triggerClicked) { - this.selectedTarget = controllerData.rayPicks[this.hand]; - if (!this.selectedTarget.intersects) { - Messages.sendLocalMessage(this.ENTITY_TOOL_UPDATES_CHANNEL, JSON.stringify({ - method: "clearSelection", - hand: hand - })); - } else { - if (this.selectedTarget.type === Picks.INTERSECTED_ENTITY) { - Messages.sendLocalMessage(this.ENTITY_TOOL_UPDATES_CHANNEL, JSON.stringify({ - method: "selectEntity", - entityID: this.selectedTarget.objectID, - hand: hand - })); - } else if (this.selectedTarget.type === Picks.INTERSECTED_OVERLAY) { - Messages.sendLocalMessage(this.ENTITY_TOOL_UPDATES_CHANNEL, JSON.stringify({ - method: "selectOverlay", - overlayID: this.selectedTarget.objectID, - hand: hand - })); - } - } - } - - this.triggerClicked = true; - } - - this.sendPointingAtData(controllerData); - }; - - this.sendPointingAtData = function(controllerData) { - var rayPick = controllerData.rayPicks[this.hand]; - var hudRayPick = controllerData.hudRayPicks[this.hand]; - var point2d = this.calculateNewReticlePosition(hudRayPick.intersection); - var desktopWindow = Window.isPointOnDesktopWindow(point2d); - var tablet = this.pointingAtTablet(rayPick.objectID); - var rightHand = this.hand === RIGHT_HAND; - Messages.sendLocalMessage(this.ENTITY_TOOL_UPDATES_CHANNEL, JSON.stringify({ - method: "pointingAt", - desktopWindow: desktopWindow, - tablet: tablet, - rightHand: rightHand - })); - }; - - this.runModule = function() { - return makeRunningValues(true, [], []); - }; - - this.exitModule = function() { - return makeRunningValues(false, [], []); - }; - - this.isReady = function(controllerData) { - if (isInEditMode()) { - if (controllerData.triggerValues[this.hand] < TRIGGER_ON_VALUE) { - this.triggerClicked = false; - } - Messages.sendLocalMessage('Hifi-unhighlight-all', ''); - return this.runModule(); - } - this.triggerClicked = false; - return this.exitModule(); - }; - - this.run = function(controllerData) { - - // Tablet stylus. - var tabletStylusInput = getEnabledModuleByName(this.hand === RIGHT_HAND - ? "RightTabletStylusInput" : "LeftTabletStylusInput"); - if (tabletStylusInput) { - var tabletReady = tabletStylusInput.isReady(controllerData); - if (tabletReady.active) { - return this.exitModule(); - } - } - - // Tablet surface. - var webLaser = getEnabledModuleByName(this.hand === RIGHT_HAND - ? "RightWebSurfaceLaserInput" : "LeftWebSurfaceLaserInput"); - if (webLaser) { - var webLaserReady = webLaser.isReady(controllerData); - var target = controllerData.rayPicks[this.hand].objectID; - this.sendPointingAtData(controllerData); - if (webLaserReady.active && this.pointingAtTablet(target)) { - return this.exitModule(); - } - } - - // HUD overlay. - if (!controllerData.triggerClicks[this.hand]) { // Don't grab if trigger pressed when laser starts intersecting. - var hudLaser = getEnabledModuleByName(this.hand === RIGHT_HAND - ? "RightHudOverlayPointer" : "LeftHudOverlayPointer"); - if (hudLaser) { - var hudLaserReady = hudLaser.isReady(controllerData); - if (hudLaserReady.active) { - return this.exitModule(); - } - } - } - - // Tablet highlight and grabbing. - var tabletHighlight = getEnabledModuleByName(this.hand === RIGHT_HAND - ? "RightNearTabletHighlight" : "LeftNearTabletHighlight"); - if (tabletHighlight) { - var tabletHighlightReady = tabletHighlight.isReady(controllerData); - if (tabletHighlightReady.active) { - return this.exitModule(); - } - } - - // Teleport. - var teleport = getEnabledModuleByName(this.hand === RIGHT_HAND ? "RightTeleporter" : "LeftTeleporter"); - if (teleport) { - var teleportReady = teleport.isReady(controllerData); - if (teleportReady.active) { - return this.exitModule(); - } - } - - if ((controllerData.triggerClicks[this.hand] === 0 && controllerData.secondaryValues[this.hand] === 0)) { - var stopRunning = false; - controllerData.nearbyOverlayIDs[this.hand].forEach(function(overlayID) { - var overlayName = Overlays.getProperty(overlayID, "name"); - if (overlayName === "KeyboardAnchor") { - stopRunning = true; - } - }); - - if (stopRunning) { - return this.exitModule(); - } - } - - this.sendPickData(controllerData); - return this.isReady(controllerData); - }; - } - - var leftHandInEditMode = new InEditMode(LEFT_HAND); - var rightHandInEditMode = new InEditMode(RIGHT_HAND); - - enableDispatcherModule("LeftHandInEditMode", leftHandInEditMode); - enableDispatcherModule("RightHandInEditMode", rightHandInEditMode); - - var INEDIT_STATUS_CHANNEL = "Hifi-InEdit-Status"; - var HAND_RAYPICK_BLACKLIST_CHANNEL = "Hifi-Hand-RayPick-Blacklist"; - this.handleMessage = function (channel, data, sender) { - if (channel === INEDIT_STATUS_CHANNEL && sender === MyAvatar.sessionUUID) { - var message; - - try { - message = JSON.parse(data); - } catch (e) { - return; - } - - switch (message.method) { - case "editing": - if (message.hand === LEFT_HAND) { - leftHandInEditMode.isEditing = message.editing; - } else { - rightHandInEditMode.isEditing = message.editing; - } - Messages.sendLocalMessage(HAND_RAYPICK_BLACKLIST_CHANNEL, JSON.stringify({ - action: "tablet", - hand: message.hand, - blacklist: message.editing - })); - break; - } - } - }; - Messages.subscribe(INEDIT_STATUS_CHANNEL); - Messages.messageReceived.connect(this.handleMessage); - - function cleanup() { - disableDispatcherModule("LeftHandInEditMode"); - disableDispatcherModule("RightHandInEditMode"); - } - - Script.scriptEnding.connect(cleanup); -}()); diff --git a/scripts/simplifiedUI/system/controllers/controllerModules/inVREditMode.js b/scripts/simplifiedUI/system/controllers/controllerModules/inVREditMode.js deleted file mode 100644 index 104e37d76c..0000000000 --- a/scripts/simplifiedUI/system/controllers/controllerModules/inVREditMode.js +++ /dev/null @@ -1,185 +0,0 @@ -"use strict"; - -// inVREditMode.js -// -// Created by David Rowe on 16 Sep 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 - -/* global Script, HMD, Messages, MyAvatar, RIGHT_HAND, LEFT_HAND, enableDispatcherModule, disableDispatcherModule, - makeDispatcherModuleParameters, makeRunningValues, getEnabledModuleByName, makeLaserParams -*/ - -Script.include("/~/system/libraries/controllerDispatcherUtils.js"); - -(function () { - - function InVREditMode(hand) { - this.hand = hand; - this.isAppActive = false; - this.isEditing = false; - this.running = false; - var NO_HAND_LASER = -1; // Invalid hand parameter so that standard laser is not displayed. - this.parameters = makeDispatcherModuleParameters( - 166, // Slightly lower priority than inEditMode. - this.hand === RIGHT_HAND - ? ["rightHand", "rightHandEquip", "rightHandTrigger"] - : ["leftHand", "leftHandEquip", "leftHandTrigger"], - [], - 100, - makeLaserParams(NO_HAND_LASER, false) - ); - - this.pointingAtTablet = function (objectID) { - return (HMD.tabletScreenID && objectID === HMD.tabletScreenID) || - (HMD.homeButtonID && objectID === HMD.homeButtonID); - }; - - // The Shapes app has a non-standard laser: in particular, the laser end dot displays on its own when the laser is - // pointing at the Shapes UI. The laser on/off is controlled by this module but the laser is implemented in the Shapes - // app. - // If, in the future, the Shapes app laser interaction is adopted as a standard UI style then the laser could be - // implemented in the controller modules along side the other laser styles. - var INVREDIT_MODULE_RUNNING = "Hifi-InVREdit-Module-Running"; - - this.runModule = function () { - if (!this.running) { - Messages.sendLocalMessage(INVREDIT_MODULE_RUNNING, JSON.stringify({ - hand: this.hand, - running: true - })); - this.running = true; - } - return makeRunningValues(true, [], []); - }; - - this.exitModule = function () { - if (this.running) { - Messages.sendLocalMessage(INVREDIT_MODULE_RUNNING, JSON.stringify({ - hand: this.hand, - running: false - })); - this.running = false; - } - return makeRunningValues(false, [], []); - }; - - this.isReady = function (controllerData) { - if (this.isAppActive) { - return makeRunningValues(true, [], []); - } - return makeRunningValues(false, [], []); - }; - - this.run = function (controllerData) { - // Default behavior if disabling is not enabled. - if (!this.isAppActive) { - return this.exitModule(); - } - - // Tablet stylus. - var tabletStylusInput = getEnabledModuleByName(this.hand === RIGHT_HAND - ? "RightTabletStylusInput" : "LeftTabletStylusInput"); - if (tabletStylusInput) { - var tabletReady = tabletStylusInput.isReady(controllerData); - if (tabletReady.active) { - return this.exitModule(); - } - } - - // Tablet surface. - var overlayLaser = getEnabledModuleByName(this.hand === RIGHT_HAND - ? "RightWebSurfaceLaserInput" : "LeftWebSurfaceLaserInput"); - if (overlayLaser) { - var overlayLaserReady = overlayLaser.isReady(controllerData); - var target = controllerData.rayPicks[this.hand].objectID; - if (overlayLaserReady.active && this.pointingAtTablet(target)) { - return this.exitModule(); - } - } - - // Tablet highlight and grabbing. - var tabletHighlight = getEnabledModuleByName(this.hand === RIGHT_HAND - ? "RightNearTabletHighlight" : "LeftNearTabletHighlight"); - if (tabletHighlight) { - var tabletHighlightReady = tabletHighlight.isReady(controllerData); - if (tabletHighlightReady.active) { - return this.exitModule(); - } - } - - // HUD overlay. - if (!controllerData.triggerClicks[this.hand]) { - var hudLaser = getEnabledModuleByName(this.hand === RIGHT_HAND - ? "RightHudOverlayPointer" : "LeftHudOverlayPointer"); - if (hudLaser) { - var hudLaserReady = hudLaser.isReady(controllerData); - if (hudLaserReady.active) { - return this.exitModule(); - } - } - } - - // Teleport. - var teleporter = getEnabledModuleByName(this.hand === RIGHT_HAND - ? "RightTeleporter" : "LeftTeleporter"); - if (teleporter) { - var teleporterReady = teleporter.isReady(controllerData); - if (teleporterReady.active) { - return this.exitModule(); - } - } - - // Other behaviors are disabled. - return this.runModule(); - }; - } - - var leftHandInVREditMode = new InVREditMode(LEFT_HAND); - var rightHandInVREditMode = new InVREditMode(RIGHT_HAND); - enableDispatcherModule("LeftHandInVREditMode", leftHandInVREditMode); - enableDispatcherModule("RightHandInVREditMode", rightHandInVREditMode); - - var INVREDIT_STATUS_CHANNEL = "Hifi-InVREdit-Status"; - var HAND_RAYPICK_BLACKLIST_CHANNEL = "Hifi-Hand-RayPick-Blacklist"; - this.handleMessage = function (channel, data, sender) { - if (channel === INVREDIT_STATUS_CHANNEL && sender === MyAvatar.sessionUUID) { - var message; - - try { - message = JSON.parse(data); - } catch (e) { - return; - } - - switch (message.method) { - case "active": - leftHandInVREditMode.isAppActive = message.active; - rightHandInVREditMode.isAppActive = message.active; - break; - case "editing": - if (message.hand === LEFT_HAND) { - leftHandInVREditMode.isEditing = message.editing; - } else { - rightHandInVREditMode.isEditing = message.editing; - } - Messages.sendLocalMessage(HAND_RAYPICK_BLACKLIST_CHANNEL, JSON.stringify({ - action: "tablet", - hand: message.hand, - blacklist: message.editing - })); - break; - } - } - }; - Messages.subscribe(INVREDIT_STATUS_CHANNEL); - Messages.messageReceived.connect(this.handleMessage); - - this.cleanup = function () { - disableDispatcherModule("LeftHandInVREditMode"); - disableDispatcherModule("RightHandInVREditMode"); - }; - Script.scriptEnding.connect(this.cleanup); -}()); diff --git a/scripts/simplifiedUI/system/controllers/controllerModules/mouseHMD.js b/scripts/simplifiedUI/system/controllers/controllerModules/mouseHMD.js deleted file mode 100644 index 172923a8e2..0000000000 --- a/scripts/simplifiedUI/system/controllers/controllerModules/mouseHMD.js +++ /dev/null @@ -1,151 +0,0 @@ -// -// mouseHMD.js -// -// scripts/system/controllers/controllerModules/ -// -// Created by Dante Ruiz 2017-9-22 -// 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 -// - -/* global Script, HMD, Reticle, Vec3, Controller */ - -(function() { - var ControllerDispatcherUtils = Script.require("/~/system/libraries/controllerDispatcherUtils.js"); - - function TimeLock(experation) { - this.experation = experation; - this.last = 0; - this.update = function(time) { - this.last = time || Date.now(); - }; - - this.expired = function(time) { - return ((time || Date.now()) - this.last) > this.experation; - }; - } - - function MouseHMD() { - var _this = this; - this.hmdWasActive = HMD.active; - this.mouseMoved = false; - this.mouseActivity = new TimeLock(5000); - this.handControllerActivity = new TimeLock(4000); - this.parameters = ControllerDispatcherUtils.makeDispatcherModuleParameters( - 10, - ["mouse"], - [], - 100); - - this.onMouseMove = function() { - _this.updateMouseActivity(); - }; - - this.onMouseClick = function() { - _this.updateMouseActivity(); - }; - - this.updateMouseActivity = function(isClick) { - if (_this.ignoreMouseActivity()) { - return; - } - - if (HMD.active) { - var now = Date.now(); - _this.mouseActivity.update(now); - } - }; - - this.adjustReticleDepth = function(controllerData) { - if (Reticle.isPointingAtSystemOverlay(Reticle.position)) { - var reticlePositionOnHUD = HMD.worldPointFromOverlay(Reticle.position); - Reticle.depth = Vec3.distance(reticlePositionOnHUD, HMD.position); - } else { - var APPARENT_MAXIMUM_DEPTH = 100.0; - var result = controllerData.mouseRayPick; - Reticle.depth = result.intersects ? result.distance : APPARENT_MAXIMUM_DEPTH; - } - }; - - this.ignoreMouseActivity = function() { - if (!Reticle.allowMouseCapture) { - return true; - } - - var pos = Reticle.position; - if (!pos || (pos.x === -1 && pos.y === -1)) { - return true; - } - - if (!_this.handControllerActivity.expired()) { - return true; - } - - return false; - }; - - this.triggersPressed = function(controllerData, now) { - var onValue = ControllerDispatcherUtils.TRIGGER_ON_VALUE; - var rightHand = ControllerDispatcherUtils.RIGHT_HAND; - var leftHand = ControllerDispatcherUtils.LEFT_HAND; - var leftTriggerValue = controllerData.triggerValues[leftHand]; - var rightTriggerValue = controllerData.triggerValues[rightHand]; - - if (leftTriggerValue > onValue || rightTriggerValue > onValue) { - this.handControllerActivity.update(now); - return true; - } - - return false; - }; - - this.isReady = function(controllerData, deltaTime) { - var now = Date.now(); - var hmdChanged = this.hmdWasActive !== HMD.active; - this.hmdWasActive = HMD.active; - this.triggersPressed(controllerData, now); - if (HMD.active) { - if (!this.mouseActivity.expired(now) && _this.handControllerActivity.expired()) { - Reticle.visible = true; - return ControllerDispatcherUtils.makeRunningValues(true, [], []); - } else { - Reticle.visible = false; - } - } else if (hmdChanged && !Reticle.visible) { - Reticle.visible = true; - } - - return ControllerDispatcherUtils.makeRunningValues(false, [], []); - }; - - this.run = function(controllerData, deltaTime) { - var now = Date.now(); - var hmdActive = HMD.active; - if (this.mouseActivity.expired(now) || this.triggersPressed(controllerData, now) || !hmdActive) { - if (!hmdActive) { - Reticle.visible = true; - } else { - Reticle.visible = false; - } - - return ControllerDispatcherUtils.makeRunningValues(false, [], []); - } - this.adjustReticleDepth(controllerData); - return ControllerDispatcherUtils.makeRunningValues(true, [], []); - }; - } - - var mouseHMD = new MouseHMD(); - ControllerDispatcherUtils.enableDispatcherModule("MouseHMD", mouseHMD); - - Controller.mouseMoveEvent.connect(mouseHMD.onMouseMove); - Controller.mousePressEvent.connect(mouseHMD.onMouseClick); - - function cleanup() { - ControllerDispatcherUtils.disableDispatcherModule("MouseHMD"); - } - - Script.scriptEnding.connect(cleanup); -})(); diff --git a/scripts/simplifiedUI/system/controllers/controllerModules/nearGrabEntity.js b/scripts/simplifiedUI/system/controllers/controllerModules/nearGrabEntity.js deleted file mode 100644 index 763c1a1ce0..0000000000 --- a/scripts/simplifiedUI/system/controllers/controllerModules/nearGrabEntity.js +++ /dev/null @@ -1,226 +0,0 @@ -"use strict"; - -// nearGrabEntity.js -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - - -/* global Script, Entities, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND, getControllerJointIndex, enableDispatcherModule, - disableDispatcherModule, Messages, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, TRIGGER_OFF_VALUE, - makeDispatcherModuleParameters, entityIsGrabbable, makeRunningValues, NEAR_GRAB_RADIUS, findGrabbableGroupParent, Vec3, - cloneEntity, entityIsCloneable, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, BUMPER_ON_VALUE, - distanceBetweenPointAndEntityBoundingBox, getGrabbableData, getEnabledModuleByName, DISPATCHER_PROPERTIES, HMD, - NEAR_GRAB_DISTANCE -*/ - -Script.include("/~/system/libraries/controllerDispatcherUtils.js"); -Script.include("/~/system/libraries/cloneEntityUtils.js"); -Script.include("/~/system/libraries/controllers.js"); - -(function() { - - function NearGrabEntity(hand) { - this.hand = hand; - this.targetEntityID = null; - this.grabbing = false; - this.cloneAllowed = true; - this.grabID = null; - - this.parameters = makeDispatcherModuleParameters( - 500, - this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"], - [], - 100); - - this.startGrab = function (targetProps) { - if (this.grabID) { - MyAvatar.releaseGrab(this.grabID); - } - - var grabData = getGrabbableData(targetProps); - - var handJointIndex; - if (HMD.mounted && HMD.isHandControllerAvailable() && grabData.grabFollowsController) { - handJointIndex = getControllerJointIndex(this.hand); - } else { - handJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"); - } - - this.targetEntityID = targetProps.id; - - var relativePosition = Entities.worldToLocalPosition(targetProps.position, MyAvatar.SELF_ID, handJointIndex); - var relativeRotation = Entities.worldToLocalRotation(targetProps.rotation, MyAvatar.SELF_ID, handJointIndex); - this.grabID = MyAvatar.grab(targetProps.id, handJointIndex, relativePosition, relativeRotation); - }; - - this.startNearGrabEntity = function (targetProps) { - Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); - - this.startGrab(targetProps); - - var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; - Entities.callEntityMethod(targetProps.id, "startNearGrab", args); - - Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({ - action: 'grab', - grabbedEntity: targetProps.id, - joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand" - })); - - this.grabbing = true; - }; - - this.endGrab = function () { - if (this.grabID) { - MyAvatar.releaseGrab(this.grabID); - this.grabID = null; - } - }; - - this.endNearGrabEntity = function () { - this.endGrab(); - - var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; - Entities.callEntityMethod(this.targetEntityID, "releaseGrab", args); - Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({ - action: 'release', - grabbedEntity: this.targetEntityID, - joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand" - })); - - this.grabbing = false; - this.targetEntityID = null; - }; - - this.getTargetProps = function (controllerData) { - // nearbyEntityProperties is already sorted by length from controller - var nearbyEntityProperties = controllerData.nearbyEntityProperties[this.hand]; - var sensorScaleFactor = MyAvatar.sensorToWorldScale; - var nearGrabDistance = NEAR_GRAB_DISTANCE * sensorScaleFactor; - var nearGrabRadius = NEAR_GRAB_RADIUS * sensorScaleFactor; - for (var i = 0; i < nearbyEntityProperties.length; i++) { - var props = nearbyEntityProperties[i]; - var grabPosition = controllerData.controllerLocations[this.hand].position; // Is offset from hand position. - var dist = distanceBetweenPointAndEntityBoundingBox(grabPosition, props); - var distance = Vec3.distance(grabPosition, props.position); - if ((dist > nearGrabDistance) || - (distance > nearGrabRadius)) { // Only smallish entities can be near grabbed. - continue; - } - if (entityIsGrabbable(props) || entityIsCloneable(props)) { - if (!entityIsCloneable(props)) { - // if we've attempted to grab a non-cloneable child, roll up to the root of the tree - var groupRootProps = findGrabbableGroupParent(controllerData, props); - if (entityIsGrabbable(groupRootProps)) { - return groupRootProps; - } - } - return props; - } - } - return null; - }; - - this.isReady = function (controllerData, deltaTime) { - this.targetEntityID = null; - this.grabbing = false; - - if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE && - controllerData.secondaryValues[this.hand] < TRIGGER_OFF_VALUE) { - this.cloneAllowed = true; - return makeRunningValues(false, [], []); - } - - var scaleModuleName = this.hand === RIGHT_HAND ? "RightScaleEntity" : "LeftScaleEntity"; - var scaleModule = getEnabledModuleByName(scaleModuleName); - if (scaleModule && (scaleModule.grabbedThingID || scaleModule.isReady(controllerData).active)) { - // we're rescaling -- don't start a grab. - return makeRunningValues(false, [], []); - } - - var targetProps = this.getTargetProps(controllerData); - if (targetProps) { - this.targetEntityID = targetProps.id; - return makeRunningValues(true, [this.targetEntityID], []); - } else { - return makeRunningValues(false, [], []); - } - }; - - this.run = function (controllerData, deltaTime) { - - if (this.grabbing) { - if (controllerData.triggerClicks[this.hand] < TRIGGER_OFF_VALUE && - controllerData.secondaryValues[this.hand] < TRIGGER_OFF_VALUE) { - this.endNearGrabEntity(); - return makeRunningValues(false, [], []); - } - - var props = controllerData.nearbyEntityPropertiesByID[this.targetEntityID]; - if (!props) { - props = Entities.getEntityProperties(this.targetEntityID, DISPATCHER_PROPERTIES); - if (!props) { - // entity was deleted - this.grabbing = false; - this.targetEntityID = null; - return makeRunningValues(false, [], []); - } - } - - var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; - Entities.callEntityMethod(this.targetEntityID, "continueNearGrab", args); - } else { - // still searching - var readiness = this.isReady(controllerData); - if (!readiness.active) { - return readiness; - } - if (controllerData.triggerClicks[this.hand] || controllerData.secondaryValues[this.hand] > BUMPER_ON_VALUE) { - // switch to grab - var targetProps = this.getTargetProps(controllerData); - var targetCloneable = entityIsCloneable(targetProps); - - if (targetCloneable) { - if (this.cloneAllowed) { - var cloneID = cloneEntity(targetProps); - if (cloneID !== null) { - var cloneProps = Entities.getEntityProperties(cloneID, DISPATCHER_PROPERTIES); - cloneProps.id = cloneID; - this.grabbing = true; - this.targetEntityID = cloneID; - this.startNearGrabEntity(cloneProps); - this.cloneAllowed = false; // prevent another clone call until inputs released - } - } - } else if (targetProps) { - this.grabbing = true; - this.startNearGrabEntity(targetProps); - } - } - } - - return makeRunningValues(true, [this.targetEntityID], []); - }; - - this.cleanup = function () { - if (this.targetEntityID) { - this.endNearGrabEntity(); - } - }; - } - - var leftNearGrabEntity = new NearGrabEntity(LEFT_HAND); - var rightNearGrabEntity = new NearGrabEntity(RIGHT_HAND); - - enableDispatcherModule("LeftNearGrabEntity", leftNearGrabEntity); - enableDispatcherModule("RightNearGrabEntity", rightNearGrabEntity); - - function cleanup() { - leftNearGrabEntity.cleanup(); - rightNearGrabEntity.cleanup(); - disableDispatcherModule("LeftNearGrabEntity"); - disableDispatcherModule("RightNearGrabEntity"); - } - Script.scriptEnding.connect(cleanup); -}()); diff --git a/scripts/simplifiedUI/system/controllers/controllerModules/nearGrabHyperLinkEntity.js b/scripts/simplifiedUI/system/controllers/controllerModules/nearGrabHyperLinkEntity.js deleted file mode 100644 index 962ae89bb9..0000000000 --- a/scripts/simplifiedUI/system/controllers/controllerModules/nearGrabHyperLinkEntity.js +++ /dev/null @@ -1,91 +0,0 @@ -"use strict"; - -// nearGrabHyperLinkEntity.js -// -// Created by Dante Ruiz on 03/02/2018 -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - -/* global Script, MyAvatar, RIGHT_HAND, LEFT_HAND, enableDispatcherModule, disableDispatcherModule, - makeDispatcherModuleParameters, makeRunningValues, TRIGGER_OFF_VALUE, NEAR_GRAB_RADIUS, BUMPER_ON_VALUE, AddressManager -*/ - -(function() { - Script.include("/~/system/libraries/controllerDispatcherUtils.js"); - Script.include("/~/system/libraries/controllers.js"); - - function NearGrabHyperLinkEntity(hand) { - this.hand = hand; - this.targetEntityID = null; - this.hyperlink = ""; - - this.parameters = makeDispatcherModuleParameters( - 485, - this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"], - [], - 100); - - - this.getTargetProps = function(controllerData) { - var nearbyEntitiesProperties = controllerData.nearbyEntityProperties[this.hand]; - var sensorScaleFactor = MyAvatar.sensorToWorldScale; - for (var i = 0; i < nearbyEntitiesProperties.length; i++) { - var props = nearbyEntitiesProperties[i]; - if (props.distance > NEAR_GRAB_RADIUS * sensorScaleFactor) { - continue; - } - if (props.href !== "" && props.href !== undefined) { - return props; - } - } - return null; - }; - - this.isReady = function(controllerData) { - this.targetEntityID = null; - if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE && - controllerData.secondaryValues[this.hand] < TRIGGER_OFF_VALUE) { - return makeRunningValues(false, [], []); - } - - var targetProps = this.getTargetProps(controllerData); - if (targetProps) { - this.hyperlink = targetProps.href; - this.targetEntityID = targetProps.id; - return makeRunningValues(true, [], []); - } - - return makeRunningValues(false, [], []); - }; - - this.run = function(controllerData) { - if ((controllerData.triggerClicks[this.hand] < TRIGGER_OFF_VALUE && - controllerData.secondaryValues[this.hand] < TRIGGER_OFF_VALUE) || this.hyperlink === "") { - return makeRunningValues(false, [], []); - } - - if (controllerData.triggerClicks[this.hand] || - controllerData.secondaryValues[this.hand] > BUMPER_ON_VALUE) { - AddressManager.handleLookupString(this.hyperlink); - return makeRunningValues(false, [], []); - } - - return makeRunningValues(true, [], []); - }; - } - - var leftNearGrabHyperLinkEntity = new NearGrabHyperLinkEntity(LEFT_HAND); - var rightNearGrabHyperLinkEntity = new NearGrabHyperLinkEntity(RIGHT_HAND); - - enableDispatcherModule("LeftNearGrabHyperLink", leftNearGrabHyperLinkEntity); - enableDispatcherModule("RightNearGrabHyperLink", rightNearGrabHyperLinkEntity); - - function cleanup() { - disableDispatcherModule("LeftNearGrabHyperLink"); - disableDispatcherModule("RightNearGrabHyperLink"); - - } - - Script.scriptEnding.connect(cleanup); -}()); diff --git a/scripts/simplifiedUI/system/controllers/controllerModules/nearParentGrabOverlay.js b/scripts/simplifiedUI/system/controllers/controllerModules/nearParentGrabOverlay.js deleted file mode 100644 index 5dcfee23cb..0000000000 --- a/scripts/simplifiedUI/system/controllers/controllerModules/nearParentGrabOverlay.js +++ /dev/null @@ -1,255 +0,0 @@ -"use strict"; - -// nearParentGrabOverlay.js -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - - -/* global Script, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND, getControllerJointIndex, - enableDispatcherModule, disableDispatcherModule, Messages, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, - makeDispatcherModuleParameters, Overlays, makeRunningValues, Vec3, resizeTablet, getTabletWidthFromSettings, - NEAR_GRAB_RADIUS, HMD, Uuid, getEnabledModuleByName -*/ - -Script.include("/~/system/libraries/controllerDispatcherUtils.js"); -Script.include("/~/system/libraries/utils.js"); - -(function() { - - // XXX this.ignoreIK = (grabbableData.ignoreIK !== undefined) ? grabbableData.ignoreIK : true; - // XXX this.kinematicGrab = (grabbableData.kinematic !== undefined) ? grabbableData.kinematic : NEAR_GRABBING_KINEMATIC; - - function NearParentingGrabOverlay(hand) { - this.hand = hand; - this.grabbedThingID = null; - this.previousParentID = {}; - this.previousParentJointIndex = {}; - this.previouslyUnhooked = {}; - this.robbed = false; - - this.parameters = makeDispatcherModuleParameters( - 90, - this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"], - [], - 100); - - - // XXX does handJointIndex change if the avatar changes? - this.handJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"); - - this.getOtherModule = function() { - return (this.hand === RIGHT_HAND) ? leftNearParentingGrabOverlay : rightNearParentingGrabOverlay; - }; - - this.otherHandIsParent = function(props) { - return this.getOtherModule().thisHandIsParent(props); - }; - - this.isGrabbedThingVisible = function() { - return Overlays.getProperty(this.grabbedThingID, "visible"); - }; - - this.thisHandIsParent = function(props) { - if (props.parentID !== MyAvatar.sessionUUID && props.parentID !== MyAvatar.SELF_ID) { - return false; - } - - var handJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"); - if (props.parentJointIndex === handJointIndex) { - return true; - } - - var controllerJointIndex = this.controllerJointIndex; - if (props.parentJointIndex === controllerJointIndex) { - return true; - } - - var controllerCRJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? - "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" : - "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND"); - - if (props.parentJointIndex === controllerCRJointIndex) { - return true; - } - - return false; - }; - - this.getGrabbedProperties = function() { - return { - position: Overlays.getProperty(this.grabbedThingID, "position"), - rotation: Overlays.getProperty(this.grabbedThingID, "rotation"), - parentID: Overlays.getProperty(this.grabbedThingID, "parentID"), - parentJointIndex: Overlays.getProperty(this.grabbedThingID, "parentJointIndex"), - dynamic: false, - shapeType: "none" - }; - }; - - - this.startNearParentingGrabOverlay = function (controllerData) { - Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); - - this.controllerJointIndex = getControllerJointIndex(this.hand); - var handJointIndex = this.controllerJointIndex; - - var grabbedProperties = this.getGrabbedProperties(); - - var reparentProps = { - parentID: MyAvatar.SELF_ID, - parentJointIndex: handJointIndex, - velocity: {x: 0, y: 0, z: 0}, - angularVelocity: {x: 0, y: 0, z: 0} - }; - - if (this.thisHandIsParent(grabbedProperties)) { - // this should never happen, but if it does, don't set previous parent to be this hand. - // this.previousParentID[this.grabbedThingID] = NULL; - // this.previousParentJointIndex[this.grabbedThingID] = -1; - } else if (this.otherHandIsParent(grabbedProperties)) { - // the other hand is parent. Steal the object and information - var otherModule = this.getOtherModule(); - this.previousParentID[this.grabbedThingID] = otherModule.previousParentID[this.grabbedThingID]; - this.previousParentJointIndex[this.grabbedThingID] = otherModule.previousParentJointIndex[this.grabbedThingID]; - otherModule.robbed = true; - } else { - this.previousParentID[this.grabbedThingID] = grabbedProperties.parentID; - this.previousParentJointIndex[this.grabbedThingID] = grabbedProperties.parentJointIndex; - } - - // resizeTablet to counter adjust offsets to account for change of scale from sensorToWorldMatrix - if (HMD.tabletID && this.grabbedThingID === HMD.tabletID) { - reparentAndScaleTablet(getTabletWidthFromSettings(), reparentProps); - } else { - Entities.editEntity(this.grabbedThingID, reparentProps); - } - - Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({ - action: 'grab', - grabbedEntity: this.grabbedThingID, - joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand" - })); - }; - - this.endNearParentingGrabOverlay = function () { - var previousParentID = this.previousParentID[this.grabbedThingID]; - if ((previousParentID === Uuid.NULL || previousParentID === null) && !this.robbed) { - Overlays.editOverlay(this.grabbedThingID, { - parentID: Uuid.NULL, - parentJointIndex: -1 - }); - } else if (!this.robbed){ - // before we grabbed it, overlay was a child of something; put it back. - Entities.editEntity(this.grabbedThingID, { - parentID: this.previousParentID[this.grabbedThingID], - parentJointIndex: this.previousParentJointIndex[this.grabbedThingID] - }); - - // resizeTablet to counter adjust offsets to account for change of scale from sensorToWorldMatrix - if (HMD.tabletID && this.grabbedThingID === HMD.tabletID) { - resizeTablet(getTabletWidthFromSettings(), this.previousParentJointIndex[this.grabbedThingID]); - } - } - - Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({ - action: 'release', - grabbedEntity: this.grabbedThingID, - joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand" - })); - - this.grabbedThingID = null; - }; - - this.getTargetID = function(overlays, controllerData) { - var sensorScaleFactor = MyAvatar.sensorToWorldScale; - for (var i = 0; i < overlays.length; i++) { - var overlayPosition = Overlays.getProperty(overlays[i], "position"); - var handPosition = controllerData.controllerLocations[this.hand].position; - var distance = Vec3.distance(overlayPosition, handPosition); - if (distance <= NEAR_GRAB_RADIUS * sensorScaleFactor) { - if (overlays[i] !== HMD.miniTabletID || controllerData.secondaryValues[this.hand] === 0) { - // Don't grab mini tablet with grip. - return overlays[i]; - } - } - } - return null; - }; - - this.isEditing = function () { - var inEditModeModule = getEnabledModuleByName(this.hand === RIGHT_HAND - ? "RightHandInEditMode" : "LeftHandInEditMode"); - if (inEditModeModule && inEditModeModule.isEditing) { - return true; - } - var inVREditModeModule = getEnabledModuleByName(this.hand === RIGHT_HAND - ? "RightHandInVREditMode" : "LeftHandInVREditMode"); - if (inVREditModeModule && inVREditModeModule.isEditing) { - return true; - } - return false; - }; - - this.isReady = function (controllerData) { - if ((controllerData.triggerClicks[this.hand] === 0 && controllerData.secondaryValues[this.hand] === 0) - || this.isEditing()) { - this.robbed = false; - return makeRunningValues(false, [], []); - } - - this.grabbedThingID = null; - - var candidateOverlays = controllerData.nearbyOverlayIDs[this.hand]; - var grabbableOverlays = candidateOverlays.filter(function(overlayID) { - return Overlays.getProperty(overlayID, "grabbable"); - }); - - var targetID = this.getTargetID(grabbableOverlays, controllerData); - if (targetID && !this.robbed) { - this.grabbedThingID = targetID; - this.startNearParentingGrabOverlay(controllerData); - return makeRunningValues(true, [this.grabbedThingID], []); - } else { - return makeRunningValues(false, [], []); - } - }; - - this.run = function (controllerData) { - if ((controllerData.triggerClicks[this.hand] === 0 && controllerData.secondaryValues[this.hand] === 0) - || this.isEditing() || !this.isGrabbedThingVisible()) { - this.endNearParentingGrabOverlay(); - this.robbed = false; - return makeRunningValues(false, [], []); - } else { - // check if someone stole the target from us - var grabbedProperties = this.getGrabbedProperties(); - if (!this.thisHandIsParent(grabbedProperties)) { - return makeRunningValues(false, [], []); - } - - return makeRunningValues(true, [this.grabbedThingID], []); - } - }; - - this.cleanup = function () { - if (this.grabbedThingID) { - this.endNearParentingGrabOverlay(); - } - }; - } - - var leftNearParentingGrabOverlay = new NearParentingGrabOverlay(LEFT_HAND); - var rightNearParentingGrabOverlay = new NearParentingGrabOverlay(RIGHT_HAND); - - enableDispatcherModule("LeftNearParentingGrabOverlay", leftNearParentingGrabOverlay); - enableDispatcherModule("RightNearParentingGrabOverlay", rightNearParentingGrabOverlay); - - function cleanup() { - leftNearParentingGrabOverlay.cleanup(); - rightNearParentingGrabOverlay.cleanup(); - disableDispatcherModule("LeftNearParentingGrabOverlay"); - disableDispatcherModule("RightNearParentingGrabOverlay"); - } - Script.scriptEnding.connect(cleanup); -}()); diff --git a/scripts/simplifiedUI/system/controllers/controllerModules/nearTabletHighlight.js b/scripts/simplifiedUI/system/controllers/controllerModules/nearTabletHighlight.js deleted file mode 100644 index 2e046f5dc6..0000000000 --- a/scripts/simplifiedUI/system/controllers/controllerModules/nearTabletHighlight.js +++ /dev/null @@ -1,135 +0,0 @@ -// -// nearTabletHighlight.js -// -// Highlight the tablet if a hand is near enough to grab it and it isn't grabbed. -// -// Created by David Rowe on 28 Aug 2018. -// Copyright 2018 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -/* global LEFT_HAND, RIGHT_HAND, makeDispatcherModuleParameters, makeRunningValues, enableDispatcherModule, - * disableDispatcherModule, getEnabledModuleByName */ - -Script.include("/~/system/libraries/controllerDispatcherUtils.js"); - -(function () { - - "use strict"; - - var TABLET_GRABBABLE_SELECTION_NAME = "tabletGrabbableSelection"; - var TABLET_GRABBABLE_SELECTION_STYLE = { - outlineUnoccludedColor: { red: 0, green: 180, blue: 239 }, // #00b4ef - outlineUnoccludedAlpha: 1, - outlineOccludedColor: { red: 0, green: 0, blue: 0 }, - outlineOccludedAlpha: 0, - fillUnoccludedColor: { red: 0, green: 0, blue: 0 }, - fillUnoccludedAlpha: 0, - fillOccludedColor: { red: 0, green: 0, blue: 0 }, - fillOccludedAlpha: 0, - outlineWidth: 4, - isOutlineSmooth: false - }; - - var isTabletNearGrabbable = [false, false]; - var isTabletHighlighted = false; - - function setTabletNearGrabbable(hand, enabled) { - if (enabled === isTabletNearGrabbable[hand]) { - return; - } - - isTabletNearGrabbable[hand] = enabled; - - if (isTabletNearGrabbable[LEFT_HAND] || isTabletNearGrabbable[RIGHT_HAND]) { - if (!isTabletHighlighted) { - Selection.addToSelectedItemsList(TABLET_GRABBABLE_SELECTION_NAME, "overlay", HMD.tabletID); - isTabletHighlighted = true; - } - } else { - if (isTabletHighlighted) { - Selection.removeFromSelectedItemsList(TABLET_GRABBABLE_SELECTION_NAME, "overlay", HMD.tabletID); - isTabletHighlighted = false; - } - } - } - - function NearTabletHighlight(hand) { - this.hand = hand; - - this.parameters = makeDispatcherModuleParameters( - 95, - this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"], - [], - 100 - ); - - this.isEditing = function () { - var inEditModeModule = getEnabledModuleByName(this.hand === RIGHT_HAND - ? "RightHandInEditMode" : "LeftHandInEditMode"); - if (inEditModeModule && inEditModeModule.isEditing) { - return true; - } - var inVREditModeModule = getEnabledModuleByName(this.hand === RIGHT_HAND - ? "RightHandInVREditMode" : "LeftHandInVREditMode"); - if (inVREditModeModule && inVREditModeModule.isEditing) { - return true; - } - return false; - }; - - this.isNearTablet = function (controllerData) { - return HMD.tabletID && controllerData.nearbyOverlayIDs[this.hand].indexOf(HMD.tabletID) !== -1; - }; - - this.isReady = function (controllerData) { - if (!this.isEditing() && this.isNearTablet(controllerData)) { - return makeRunningValues(true, [], []); - } - setTabletNearGrabbable(this.hand, false); - return makeRunningValues(false, [], []); - }; - - this.run = function (controllerData) { - if (this.isEditing() || !this.isNearTablet(controllerData)) { - setTabletNearGrabbable(this.hand, false); - return makeRunningValues(false, [], []); - } - - if (controllerData.triggerClicks[this.hand] || controllerData.secondaryValues[this.hand]) { - setTabletNearGrabbable(this.hand, false); - return makeRunningValues(false, [], []); - } - - setTabletNearGrabbable(this.hand, true); - return makeRunningValues(true, [], []); - }; - } - - var leftNearTabletHighlight = new NearTabletHighlight(LEFT_HAND); - var rightNearTabletHighlight = new NearTabletHighlight(RIGHT_HAND); - enableDispatcherModule("LeftNearTabletHighlight", leftNearTabletHighlight); - enableDispatcherModule("RightNearTabletHighlight", rightNearTabletHighlight); - - function onDisplayModeChanged() { - if (HMD.active) { - Selection.enableListHighlight(TABLET_GRABBABLE_SELECTION_NAME, TABLET_GRABBABLE_SELECTION_STYLE); - } else { - Selection.disableListHighlight(TABLET_GRABBABLE_SELECTION_NAME); - Selection.clearSelectedItemsList(TABLET_GRABBABLE_SELECTION_NAME); - } - } - HMD.displayModeChanged.connect(onDisplayModeChanged); - HMD.mountedChanged.connect(onDisplayModeChanged); - onDisplayModeChanged(); - - function cleanUp() { - disableDispatcherModule("LeftNearTabletHighlight"); - disableDispatcherModule("RightNearTabletHighlight"); - Selection.disableListHighlight(TABLET_GRABBABLE_SELECTION_NAME); - } - Script.scriptEnding.connect(cleanUp); - -}()); diff --git a/scripts/simplifiedUI/system/controllers/controllerModules/nearTrigger.js b/scripts/simplifiedUI/system/controllers/controllerModules/nearTrigger.js deleted file mode 100644 index 4bff4ea3f0..0000000000 --- a/scripts/simplifiedUI/system/controllers/controllerModules/nearTrigger.js +++ /dev/null @@ -1,120 +0,0 @@ -"use strict"; - -// nearTrigger.js -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - - -/* global Script, Entities, MyAvatar, RIGHT_HAND, LEFT_HAND, enableDispatcherModule, disableDispatcherModule, getGrabbableData, - Vec3, TRIGGER_OFF_VALUE, makeDispatcherModuleParameters, makeRunningValues, NEAR_GRAB_RADIUS -*/ - -Script.include("/~/system/libraries/controllerDispatcherUtils.js"); - -(function() { - - function entityWantsNearTrigger(props) { - var grabbableData = getGrabbableData(props); - return grabbableData.triggerable; - } - - function NearTriggerEntity(hand) { - this.hand = hand; - this.targetEntityID = null; - this.grabbing = false; - this.previousParentID = {}; - this.previousParentJointIndex = {}; - this.previouslyUnhooked = {}; - this.startSent = false; - - this.parameters = makeDispatcherModuleParameters( - 480, - this.hand === RIGHT_HAND ? ["rightHandTrigger", "rightHand"] : ["leftHandTrigger", "leftHand"], - [], - 100); - - this.getTargetProps = function (controllerData) { - // nearbyEntityProperties is already sorted by length from controller - var nearbyEntityProperties = controllerData.nearbyEntityProperties[this.hand]; - var sensorScaleFactor = MyAvatar.sensorToWorldScale; - for (var i = 0; i < nearbyEntityProperties.length; i++) { - var props = nearbyEntityProperties[i]; - var handPosition = controllerData.controllerLocations[this.hand].position; - var distance = Vec3.distance(props.position, handPosition); - if (distance > NEAR_GRAB_RADIUS * sensorScaleFactor) { - continue; - } - if (entityWantsNearTrigger(props)) { - return props; - } - } - return null; - }; - - this.startNearTrigger = function (controllerData) { - var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; - Entities.callEntityMethod(this.targetEntityID, "startNearTrigger", args); - }; - - this.continueNearTrigger = function (controllerData) { - var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; - Entities.callEntityMethod(this.targetEntityID, "continueNearTrigger", args); - }; - - this.endNearTrigger = function (controllerData) { - var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; - Entities.callEntityMethod(this.targetEntityID, "stopNearTrigger", args); - }; - - this.isReady = function (controllerData) { - this.targetEntityID = null; - - if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE) { - return makeRunningValues(false, [], []); - } - - var targetProps = this.getTargetProps(controllerData); - if (targetProps) { - this.targetEntityID = targetProps.id; - return makeRunningValues(true, [this.targetEntityID], []); - } else { - return makeRunningValues(false, [], []); - } - }; - - this.run = function (controllerData) { - if (!this.startSent) { - this.startNearTrigger(controllerData); - this.startSent = true; - } else if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE) { - this.endNearTrigger(controllerData); - this.startSent = false; - return makeRunningValues(false, [], []); - } else { - this.continueNearTrigger(controllerData); - } - return makeRunningValues(true, [this.targetEntityID], []); - }; - - this.cleanup = function () { - if (this.targetEntityID) { - this.endNearTrigger(); - } - }; - } - - var leftNearTriggerEntity = new NearTriggerEntity(LEFT_HAND); - var rightNearTriggerEntity = new NearTriggerEntity(RIGHT_HAND); - - enableDispatcherModule("LeftNearTriggerEntity", leftNearTriggerEntity); - enableDispatcherModule("RightNearTriggerEntity", rightNearTriggerEntity); - - function cleanup() { - leftNearTriggerEntity.cleanup(); - rightNearTriggerEntity.cleanup(); - disableDispatcherModule("LeftNearTriggerEntity"); - disableDispatcherModule("RightNearTriggerEntity"); - } - Script.scriptEnding.connect(cleanup); -}()); diff --git a/scripts/simplifiedUI/system/controllers/controllerModules/pushToTalk.js b/scripts/simplifiedUI/system/controllers/controllerModules/pushToTalk.js deleted file mode 100644 index 11335ba2f5..0000000000 --- a/scripts/simplifiedUI/system/controllers/controllerModules/pushToTalk.js +++ /dev/null @@ -1,64 +0,0 @@ -"use strict"; - -// Created by Jason C. Najera on 3/7/2019 -// Copyright 2019 High Fidelity, Inc. -// -// Handles Push-to-Talk functionality for HMD mode. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - -Script.include("/~/system/libraries/controllerDispatcherUtils.js"); -Script.include("/~/system/libraries/controllers.js"); - -(function() { // BEGIN LOCAL_SCOPE - function PushToTalkHandler() { - var _this = this; - this.active = false; - - this.shouldTalk = function (controllerData) { - // Set up test against controllerData here... - var gripVal = controllerData.secondaryValues[LEFT_HAND] && controllerData.secondaryValues[RIGHT_HAND]; - return (gripVal) ? true : false; - }; - - this.shouldStopTalking = function (controllerData) { - var gripVal = controllerData.secondaryValues[LEFT_HAND] && controllerData.secondaryValues[RIGHT_HAND]; - return (gripVal) ? false : true; - }; - - this.isReady = function (controllerData, deltaTime) { - if (HMD.active && Audio.pushToTalk && this.shouldTalk(controllerData)) { - Audio.pushingToTalk = true; - return makeRunningValues(true, [], []); - } - - return makeRunningValues(false, [], []); - }; - - this.run = function (controllerData, deltaTime) { - if (this.shouldStopTalking(controllerData) || !Audio.pushToTalk) { - Audio.pushingToTalk = false; - print("Stop pushing to talk."); - return makeRunningValues(false, [], []); - } - - return makeRunningValues(true, [], []); - }; - - this.parameters = makeDispatcherModuleParameters( - 950, - ["head"], - [], - 100); - } - - var pushToTalk = new PushToTalkHandler(); - enableDispatcherModule("PushToTalk", pushToTalk); - - function cleanup() { - disableDispatcherModule("PushToTalk"); - }; - - Script.scriptEnding.connect(cleanup); -}()); // END LOCAL_SCOPE diff --git a/scripts/simplifiedUI/system/controllers/controllerModules/scaleAvatar.js b/scripts/simplifiedUI/system/controllers/controllerModules/scaleAvatar.js deleted file mode 100644 index 1868b0228a..0000000000 --- a/scripts/simplifiedUI/system/controllers/controllerModules/scaleAvatar.js +++ /dev/null @@ -1,88 +0,0 @@ -// scaleAvatar.js -// -// Created by Dante Ruiz on 9/11/17 -// -// Grabs physically moveable entities with hydra-like controllers; it works for either near or far objects. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - -/* global Script, Vec3, MyAvatar, RIGHT_HAND */ - -(function () { - var dispatcherUtils = Script.require("/~/system/libraries/controllerDispatcherUtils.js"); - - function clamp(val, min, max) { - return Math.max(min, Math.min(max, val)); - } - - function ScaleAvatar(hand) { - this.hand = hand; - this.scalingStartAvatarScale = 0; - this.scalingStartDistance = 0; - - this.parameters = dispatcherUtils.makeDispatcherModuleParameters( - 120, - this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"], - [], - 100 - ); - - this.otherHand = function() { - return this.hand === dispatcherUtils.RIGHT_HAND ? dispatcherUtils.LEFT_HAND : dispatcherUtils.RIGHT_HAND; - }; - - this.getOtherModule = function() { - var otherModule = this.hand === dispatcherUtils.RIGHT_HAND ? leftScaleAvatar : rightScaleAvatar; - return otherModule; - }; - - this.triggersPressed = function(controllerData) { - if (controllerData.triggerClicks[this.hand] && - controllerData.secondaryValues[this.hand] > dispatcherUtils.BUMPER_ON_VALUE) { - return true; - } - return false; - }; - - this.isReady = function(controllerData) { - var otherModule = this.getOtherModule(); - if (this.triggersPressed(controllerData) && otherModule.triggersPressed(controllerData)) { - this.scalingStartAvatarScale = MyAvatar.scale; - this.scalingStartDistance = Vec3.length(Vec3.subtract(controllerData.controllerLocations[this.hand].position, - controllerData.controllerLocations[this.otherHand()].position)); - return dispatcherUtils.makeRunningValues(true, [], []); - } - return dispatcherUtils.makeRunningValues(false, [], []); - }; - - this.run = function(controllerData) { - var otherModule = this.getOtherModule(); - if (this.triggersPressed(controllerData) && otherModule.triggersPressed(controllerData)) { - if (this.hand === dispatcherUtils.RIGHT_HAND) { - var scalingCurrentDistance = - Vec3.length(Vec3.subtract(controllerData.controllerLocations[this.hand].position, - controllerData.controllerLocations[this.otherHand()].position)); - - var newAvatarScale = (scalingCurrentDistance / this.scalingStartDistance) * this.scalingStartAvatarScale; - MyAvatar.scale = clamp(newAvatarScale, MyAvatar.getDomainMinScale(), MyAvatar.getDomainMaxScale()); - MyAvatar.scaleChanged(); - } - return dispatcherUtils.makeRunningValues(true, [], []); - } - return dispatcherUtils.makeRunningValues(false, [], []); - }; - } - - var leftScaleAvatar = new ScaleAvatar(dispatcherUtils.LEFT_HAND); - var rightScaleAvatar = new ScaleAvatar(dispatcherUtils.RIGHT_HAND); - - dispatcherUtils.enableDispatcherModule("LeftScaleAvatar", leftScaleAvatar); - dispatcherUtils.enableDispatcherModule("RightScaleAvatar", rightScaleAvatar); - - function cleanup() { - dispatcherUtils.disableDispatcherModule("LeftScaleAvatar"); - dispatcherUtils.disableDispatcherModule("RightScaleAvatar"); - } - Script.scriptEnding.connect(cleanup); -})(); diff --git a/scripts/simplifiedUI/system/controllers/controllerModules/scaleEntity.js b/scripts/simplifiedUI/system/controllers/controllerModules/scaleEntity.js deleted file mode 100644 index 50b6c5b853..0000000000 --- a/scripts/simplifiedUI/system/controllers/controllerModules/scaleEntity.js +++ /dev/null @@ -1,110 +0,0 @@ -// scaleEntity.js -// -// Created by Dante Ruiz on 9/18/17 -// -// Grabs physically moveable entities with hydra-like controllers; it works for either near or far objects. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - -/* global Script, Vec3, MyAvatar, Entities, RIGHT_HAND, entityIsGrabbable */ - -(function() { - var dispatcherUtils = Script.require("/~/system/libraries/controllerDispatcherUtils.js"); - function ScaleEntity(hand) { - this.hand = hand; - this.grabbedThingID = false; - this.scalingStartDistance = false; - this.scalingStartDimensions = false; - - this.parameters = dispatcherUtils.makeDispatcherModuleParameters( - 120, - this.hand === RIGHT_HAND ? ["rightHandTrigger"] : ["leftHandTrigger"], - [], - 100 - ); - - this.otherHand = function() { - return this.hand === dispatcherUtils.RIGHT_HAND ? dispatcherUtils.LEFT_HAND : dispatcherUtils.RIGHT_HAND; - }; - - this.otherModule = function() { - return this.hand === dispatcherUtils.RIGHT_HAND ? leftScaleEntity : rightScaleEntity; - }; - - this.bumperPressed = function(controllerData) { - return ( controllerData.secondaryValues[this.hand] > dispatcherUtils.BUMPER_ON_VALUE); - }; - - this.getTargetProps = function(controllerData) { - // nearbyEntityProperties is already sorted by length from controller - var nearbyEntityProperties = controllerData.nearbyEntityProperties[this.hand]; - var sensorScaleFactor = MyAvatar.sensorToWorldScale; - for (var i = 0; i < nearbyEntityProperties.length; i++) { - var props = nearbyEntityProperties[i]; - var handPosition = controllerData.controllerLocations[this.hand].position; - var distance = Vec3.distance(props.position, handPosition); - if (distance > dispatcherUtils.NEAR_GRAB_RADIUS * sensorScaleFactor) { - continue; - } - if ((dispatcherUtils.entityIsGrabbable(props) || - dispatcherUtils.propsArePhysical(props)) && !props.locked) { - return props; - } - } - return null; - }; - - this.isReady = function(controllerData) { - var otherModule = this.otherModule(); - if (this.bumperPressed(controllerData) && otherModule.bumperPressed(controllerData)) { - var thisHandTargetProps = this.getTargetProps(controllerData); - var otherHandTargetProps = otherModule.getTargetProps(controllerData); - if (thisHandTargetProps && otherHandTargetProps) { - if (thisHandTargetProps.id === otherHandTargetProps.id) { - if (!entityIsGrabbable(thisHandTargetProps)) { - return dispatcherUtils.makeRunningValues(false, [], []); - } - this.grabbedThingID = thisHandTargetProps.id; - this.scalingStartDistance = - Vec3.length(Vec3.subtract(controllerData.controllerLocations[this.hand].position, - controllerData.controllerLocations[this.otherHand()].position)); - this.scalingStartDimensions = thisHandTargetProps.dimensions; - return dispatcherUtils.makeRunningValues(true, [], []); - } - } - } - this.grabbedThingID = false; - return dispatcherUtils.makeRunningValues(false, [], []); - }; - - this.run = function(controllerData) { - var otherModule = this.otherModule(); - if (this.bumperPressed(controllerData) && otherModule.bumperPressed(controllerData)) { - if (this.hand === dispatcherUtils.RIGHT_HAND) { - var scalingCurrentDistance = - Vec3.length(Vec3.subtract(controllerData.controllerLocations[this.hand].position, - controllerData.controllerLocations[this.otherHand()].position)); - var currentRescale = scalingCurrentDistance / this.scalingStartDistance; - var newDimensions = Vec3.multiply(currentRescale, this.scalingStartDimensions); - Entities.editEntity(this.grabbedThingID, { localDimensions: newDimensions }); - } - return dispatcherUtils.makeRunningValues(true, [], []); - } - this.grabbedThingID = false; - return dispatcherUtils.makeRunningValues(false, [], []); - }; - } - - var leftScaleEntity = new ScaleEntity(dispatcherUtils.LEFT_HAND); - var rightScaleEntity = new ScaleEntity(dispatcherUtils.RIGHT_HAND); - - dispatcherUtils.enableDispatcherModule("LeftScaleEntity", leftScaleEntity); - dispatcherUtils.enableDispatcherModule("RightScaleEntity", rightScaleEntity); - - function cleanup() { - dispatcherUtils.disableDispatcherModule("LeftScaleEntity"); - dispatcherUtils.disableDispatcherModule("RightScaleEntity"); - } - Script.scriptEnding.connect(cleanup); -})(); diff --git a/scripts/simplifiedUI/system/controllers/controllerModules/stylusInput.js b/scripts/simplifiedUI/system/controllers/controllerModules/stylusInput.js deleted file mode 100644 index c4aa9efd50..0000000000 --- a/scripts/simplifiedUI/system/controllers/controllerModules/stylusInput.js +++ /dev/null @@ -1,220 +0,0 @@ -"use strict"; - -// stylusInput.js -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - -/* global Script, MyAvatar, Controller, Uuid, RIGHT_HAND, LEFT_HAND, enableDispatcherModule, disableDispatcherModule, - makeRunningValues, Vec3, makeDispatcherModuleParameters, Overlays, HMD, Settings, getEnabledModuleByName, Pointers, - Picks, PickType -*/ - -Script.include("/~/system/libraries/controllerDispatcherUtils.js"); -Script.include("/~/system/libraries/controllers.js"); - -(function() { - function isNearStylusTarget(stylusTargets, maxNormalDistance) { - var stylusTargetIDs = []; - for (var index = 0; index < stylusTargets.length; index++) { - var stylusTarget = stylusTargets[index]; - if (stylusTarget.distance <= maxNormalDistance && !(HMD.tabletID && stylusTarget.id === HMD.tabletID)) { - stylusTargetIDs.push(stylusTarget.id); - } - } - return stylusTargetIDs; - } - - function getOverlayDistance(controllerPosition, overlayID) { - var position = Overlays.getProperty(overlayID, "position"); - return { - id: overlayID, - distance: Vec3.distance(position, controllerPosition) - }; - } - - function StylusInput(hand) { - this.hand = hand; - - this.parameters = makeDispatcherModuleParameters( - 100, - this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"], - [], - 100); - - this.pointer = Pointers.createPointer(PickType.Stylus, { - hand: this.hand, - filter: Picks.PICK_OVERLAYS, - hover: true, - enabled: true - }); - - this.disable = false; - - this.otherModuleNeedsToRun = function(controllerData) { - var grabOverlayModuleName = this.hand === RIGHT_HAND ? "RightNearParentingGrabOverlay" : "LeftNearParentingGrabOverlay"; - var grabOverlayModule = getEnabledModuleByName(grabOverlayModuleName); - var grabEntityModuleName = this.hand === RIGHT_HAND ? "RightNearParentingGrabEntity" : "LeftNearParentingGrabEntity"; - var grabEntityModule = getEnabledModuleByName(grabEntityModuleName); - var grabOverlayModuleReady = grabOverlayModule ? grabOverlayModule.isReady(controllerData) : makeRunningValues(false, [], []); - var grabEntityModuleReady = grabEntityModule ? grabEntityModule.isReady(controllerData) : makeRunningValues(false, [], []); - var farGrabModuleName = this.hand === RIGHT_HAND ? "RightFarActionGrabEntity" : "LeftFarActionGrabEntity"; - var farGrabModule = getEnabledModuleByName(farGrabModuleName); - var farGrabModuleReady = farGrabModule ? farGrabModule.isReady(controllerData) : makeRunningValues(false, [], []); - var nearTabletHighlightModuleName = - this.hand === RIGHT_HAND ? "RightNearTabletHighlight" : "LeftNearTabletHighlight"; - var nearTabletHighlightModule = getEnabledModuleByName(nearTabletHighlightModuleName); - var nearTabletHighlightModuleReady = nearTabletHighlightModule - ? nearTabletHighlightModule.isReady(controllerData) : makeRunningValues(false, [], []); - return grabOverlayModuleReady.active || farGrabModuleReady.active || grabEntityModuleReady.active - || nearTabletHighlightModuleReady.active; - }; - - this.overlayLaserActive = function(controllerData) { - var rightOverlayLaserModule = getEnabledModuleByName("RightWebSurfaceLaserInput"); - var leftOverlayLaserModule = getEnabledModuleByName("LeftWebSurfaceLaserInput"); - var rightModuleRunning = rightOverlayLaserModule ? rightOverlayLaserModule.isReady(controllerData).active : false; - var leftModuleRunning = leftOverlayLaserModule ? leftOverlayLaserModule.isReady(controllerData).active : false; - return leftModuleRunning || rightModuleRunning; - }; - - this.processStylus = function(controllerData) { - if (this.overlayLaserActive(controllerData) || this.otherModuleNeedsToRun(controllerData)) { - Pointers.setRenderState(this.pointer, "disabled"); - return false; - } - - var sensorScaleFactor = MyAvatar.sensorToWorldScale; - - // build list of stylus targets, near the stylusTip - var stylusTargets = []; - var candidateOverlays = controllerData.nearbyOverlayIDs; - var controllerPosition = controllerData.controllerLocations[this.hand].position; - var i, stylusTarget; - - for (i = 0; i < candidateOverlays.length; i++) { - if (!(HMD.tabletID && candidateOverlays[i] === HMD.tabletID) && - Overlays.getProperty(candidateOverlays[i], "visible")) { - stylusTarget = getOverlayDistance(controllerPosition, candidateOverlays[i]); - if (stylusTarget) { - stylusTargets.push(stylusTarget); - } - } - } - - // add the tabletScreen, if it is valid - if (HMD.tabletScreenID && HMD.tabletScreenID !== Uuid.NULL && - Overlays.getProperty(HMD.tabletScreenID, "visible")) { - stylusTarget = getOverlayDistance(controllerPosition, HMD.tabletScreenID); - if (stylusTarget) { - stylusTargets.push(stylusTarget); - } - } - - // add the tablet home button. - if (HMD.homeButtonID && HMD.homeButtonID !== Uuid.NULL && - Overlays.getProperty(HMD.homeButtonID, "visible")) { - stylusTarget = getOverlayDistance(controllerPosition, HMD.homeButtonID); - if (stylusTarget) { - stylusTargets.push(stylusTarget); - } - } - - // Add the mini tablet. - if (HMD.miniTabletScreenID && Overlays.getProperty(HMD.miniTabletScreenID, "visible")) { - stylusTarget = getOverlayDistance(controllerPosition, HMD.miniTabletScreenID); - if (stylusTarget) { - stylusTargets.push(stylusTarget); - } - } - - const WEB_DISPLAY_STYLUS_DISTANCE = (Keyboard.raised && Keyboard.preferMalletsOverLasers) ? 0.2 : 0.5; - var nearStylusTarget = isNearStylusTarget(stylusTargets, WEB_DISPLAY_STYLUS_DISTANCE * sensorScaleFactor); - - if (nearStylusTarget.length !== 0) { - if (!this.disable) { - Pointers.setRenderState(this.pointer,"events on"); - Pointers.setIncludeItems(this.pointer, nearStylusTarget); - } else { - Pointers.setRenderState(this.pointer,"events off"); - } - return true; - } else { - Pointers.setRenderState(this.pointer, "disabled"); - Pointers.setIncludeItems(this.pointer, []); - return false; - } - }; - - this.isReady = function (controllerData) { - var PREFER_STYLUS_OVER_LASER = "preferStylusOverLaser"; - var isUsingStylus = Settings.getValue(PREFER_STYLUS_OVER_LASER, false); - - if (isUsingStylus && this.processStylus(controllerData)) { - Pointers.enablePointer(this.pointer); - this.hand === RIGHT_HAND ? Keyboard.disableRightMallet() : Keyboard.disableLeftMallet(); - return makeRunningValues(true, [], []); - } else { - Pointers.disablePointer(this.pointer); - if (Keyboard.raised && Keyboard.preferMalletsOverLasers) { - this.hand === RIGHT_HAND ? Keyboard.enableRightMallet() : Keyboard.enableLeftMallet(); - } - return makeRunningValues(false, [], []); - } - }; - - this.run = function (controllerData, deltaTime) { - return this.isReady(controllerData); - }; - - this.cleanup = function () { - Pointers.removePointer(this.pointer); - }; - } - - function mouseHoverEnter(overlayID, event) { - if (event.id === leftTabletStylusInput.pointer && !rightTabletStylusInput.disable && !leftTabletStylusInput.disable) { - rightTabletStylusInput.disable = true; - } else if (event.id === rightTabletStylusInput.pointer && !leftTabletStylusInput.disable && !rightTabletStylusInput.disable) { - leftTabletStylusInput.disable = true; - } - } - - function mouseHoverLeave(overlayID, event) { - if (event.id === leftTabletStylusInput.pointer) { - rightTabletStylusInput.disable = false; - } else if (event.id === rightTabletStylusInput.pointer) { - leftTabletStylusInput.disable = false; - } - } - - var HAPTIC_STYLUS_STRENGTH = 1.0; - var HAPTIC_STYLUS_DURATION = 20.0; - function mousePress(overlayID, event) { - if (HMD.active) { - if (event.id === leftTabletStylusInput.pointer && event.button === "Primary") { - Controller.triggerHapticPulse(HAPTIC_STYLUS_STRENGTH, HAPTIC_STYLUS_DURATION, LEFT_HAND); - } else if (event.id === rightTabletStylusInput.pointer && event.button === "Primary") { - Controller.triggerHapticPulse(HAPTIC_STYLUS_STRENGTH, HAPTIC_STYLUS_DURATION, RIGHT_HAND); - } - } - } - - var leftTabletStylusInput = new StylusInput(LEFT_HAND); - var rightTabletStylusInput = new StylusInput(RIGHT_HAND); - - enableDispatcherModule("LeftTabletStylusInput", leftTabletStylusInput); - enableDispatcherModule("RightTabletStylusInput", rightTabletStylusInput); - - Overlays.hoverEnterOverlay.connect(mouseHoverEnter); - Overlays.hoverLeaveOverlay.connect(mouseHoverLeave); - Overlays.mousePressOnOverlay.connect(mousePress); - - this.cleanup = function () { - leftTabletStylusInput.cleanup(); - rightTabletStylusInput.cleanup(); - disableDispatcherModule("LeftTabletStylusInput"); - disableDispatcherModule("RightTabletStylusInput"); - }; - Script.scriptEnding.connect(this.cleanup); -}()); diff --git a/scripts/simplifiedUI/system/controllers/controllerModules/teleport.js b/scripts/simplifiedUI/system/controllers/controllerModules/teleport.js deleted file mode 100644 index 5a51773930..0000000000 --- a/scripts/simplifiedUI/system/controllers/controllerModules/teleport.js +++ /dev/null @@ -1,1108 +0,0 @@ -"use strict"; - -// Created by james b. pollack @imgntn on 7/2/2016 -// Copyright 2016 High Fidelity, Inc. -// -// Creates a beam and target and then teleports you there. Release when its close to you to cancel. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - -/* jslint bitwise: true */ - -/* global Script, Entities, MyAvatar, Controller, Quat, RIGHT_HAND, LEFT_HAND, - enableDispatcherModule, disableDispatcherModule, Messages, makeDispatcherModuleParameters, makeRunningValues, Vec3, - HMD, Uuid, AvatarList, Picks, Pointers, PickType -*/ - -Script.include("/~/system/libraries/Xform.js"); -Script.include("/~/system/libraries/controllerDispatcherUtils.js"); -Script.include("/~/system/libraries/controllers.js"); - -(function() { // BEGIN LOCAL_SCOPE - - var TARGET_MODEL_URL = Script.resolvePath("../../assets/models/teleportationSpotBasev8.fbx"); - var SEAT_MODEL_URL = Script.resolvePath("../../assets/models/teleport-seat.fbx"); - - var TARGET_MODEL_DIMENSIONS = { x: 0.6552, y: 0.3063, z: 0.6552 }; - - var COLORS_TELEPORT_SEAT = { - red: 255, - green: 0, - blue: 170 - }; - - var COLORS_TELEPORT_CAN_TELEPORT = { - red: 97, - green: 247, - blue: 255 - }; - - var COLORS_TELEPORT_CANCEL = { - red: 255, - green: 184, - blue: 73 - }; - - var handInfo = { - right: { - controllerInput: Controller.Standard.RightHand - }, - left: { - controllerInput: Controller.Standard.LeftHand - } - }; - - var cancelPath = { - color: COLORS_TELEPORT_CANCEL, - alpha: 0.3, - width: 0.025, - drawInFront: true - }; - - var teleportPath = { - color: COLORS_TELEPORT_CAN_TELEPORT, - alpha: 0.7, - width: 0.025, - drawInFront: true - }; - - var seatPath = { - color: COLORS_TELEPORT_SEAT, - alpha: 0.7, - width: 0.025, - drawInFront: true - }; - - var teleportEnd = { - type: "model", - url: TARGET_MODEL_URL, - dimensions: TARGET_MODEL_DIMENSIONS, - ignorePickIntersection: true - }; - - var seatEnd = { - type: "model", - url: SEAT_MODEL_URL, - dimensions: TARGET_MODEL_DIMENSIONS, - ignorePickIntersection: true - }; - - var collisionEnd = { - type: "shape", - shape: "box", - dimensions: { x: 1.0, y: 0.001, z: 1.0 }, - alpha: 0.0, - ignorePickIntersection: true - }; - - var teleportRenderStates = [{name: "cancel", path: cancelPath}, - {name: "teleport", path: teleportPath, end: teleportEnd}, - {name: "seat", path: seatPath, end: seatEnd}, - {name: "collision", end: collisionEnd}]; - - var DEFAULT_DISTANCE = 8.0; - var teleportDefaultRenderStates = [{name: "cancel", distance: DEFAULT_DISTANCE, path: cancelPath}]; - - var ignoredEntities = []; - - var TELEPORTER_STATES = { - IDLE: 'idle', - TARGETTING: 'targetting', - TARGETTING_INVALID: 'targetting_invalid' - }; - - var TARGET = { - NONE: 'none', // Not currently targetting anything - INVALID: 'invalid', // The current target is invalid (wall, ceiling, etc.) - COLLIDES: 'collides', // Insufficient space to accommodate the avatar capsule - DISCREPANCY: 'discrepancy', // We are not 100% sure the avatar will fit so we trigger safe landing - SURFACE: 'surface', // The current target is a valid surface - SEAT: 'seat' // The current target is a seat - }; - - var speed = 9.3; - var accelerationAxis = {x: 0.0, y: -5.0, z: 0.0}; - - function Teleporter(hand) { - var _this = this; - this.init = false; - this.hand = hand; - this.buttonValue = 0; - this.standardAxisLY = 0.0; - this.standardAxisRY = 0.0; - this.disabled = false; // used by the 'Hifi-Teleport-Disabler' message handler - this.active = false; - this.state = TELEPORTER_STATES.IDLE; - this.currentTarget = TARGET.INVALID; - this.currentResult = null; - this.capsuleThreshold = 0.05; - this.pickHeightOffset = 0.05; - - this.getOtherModule = function() { - var otherModule = this.hand === RIGHT_HAND ? leftTeleporter : rightTeleporter; - return otherModule; - }; - - this.teleportHeadCollisionPick; - this.teleportHandCollisionPick; - this.teleportParabolaHandVisuals; - this.teleportParabolaHandCollisions; - this.teleportParabolaHeadVisuals; - this.teleportParabolaHeadCollisions; - - - this.PLAY_AREA_OVERLAY_MODEL = Script.resolvePath("../../assets/models/trackingSpacev18.fbx"); - this.PLAY_AREA_OVERLAY_MODEL_DIMENSIONS = { x: 1.969, y: 0.001, z: 1.969 }; - this.PLAY_AREA_FLOAT_ABOVE_FLOOR = 0.005; - this.PLAY_AREA_OVERLAY_OFFSET = // Offset from floor. - { x: 0, y: this.PLAY_AREA_OVERLAY_MODEL_DIMENSIONS.y / 2 + this.PLAY_AREA_FLOAT_ABOVE_FLOOR, z: 0 }; - this.PLAY_AREA_SENSOR_OVERLAY_MODEL = Script.resolvePath("../../assets/models/oculusSensorv11.fbx"); - this.PLAY_AREA_SENSOR_OVERLAY_DIMENSIONS = { x: 0.1198, y: 0.2981, z: 0.1198 }; - this.PLAY_AREA_SENSOR_OVERLAY_ROTATION = Quat.fromVec3Degrees({ x: 0, y: -90, z: 0 }); - this.PLAY_AREA_BOX_ALPHA = 1.0; - this.PLAY_AREA_SENSOR_ALPHA = 0.8; - this.playAreaSensorPositions = []; - this.playArea = { x: 0, y: 0 }; - this.playAreaCenterOffset = this.PLAY_AREA_OVERLAY_OFFSET; - this.isPlayAreaVisible = false; - this.wasPlayAreaVisible = false; - this.isPlayAreaAvailable = false; - this.targetOverlayID = null; - this.playAreaOverlay = null; - this.playAreaSensorPositionOverlays = []; - - this.TELEPORT_SCALE_DURATION = 130; - this.TELEPORT_SCALE_TIMEOUT = 25; - this.isTeleportVisible = false; - this.teleportScaleTimer = null; - this.teleportScaleStart = 0; - this.teleportScaleFactor = 0; - this.teleportScaleMode = "head"; - - this.TELEPORTED_FADE_DELAY_DURATION = 900; - this.TELEPORTED_FADE_DURATION = 200; - this.TELEPORTED_FADE_INTERVAL = 25; - this.TELEPORTED_FADE_DELAY_DELTA = this.TELEPORTED_FADE_INTERVAL / this.TELEPORTED_FADE_DELAY_DURATION; - this.TELEPORTED_FADE_DELTA = this.TELEPORTED_FADE_INTERVAL / this.TELEPORTED_FADE_DURATION; - this.teleportedFadeTimer = null; - this.teleportedFadeDelayFactor = 0; - this.teleportedFadeFactor = 0; - this.teleportedPosition = Vec3.ZERO; - this.TELEPORTED_TARGET_ALPHA = 1.0; - this.TELEPORTED_TARGET_ROTATION = Quat.fromVec3Degrees({ x: 0, y: 180, z: 0 }); - this.teleportedTargetOverlay = null; - - this.setPlayAreaDimensions = function () { - var avatarScale = MyAvatar.sensorToWorldScale; - - var playAreaOverlayProperties = { - dimensions: - Vec3.multiply(_this.teleportScaleFactor * avatarScale, { - x: _this.playArea.width, - y: _this.PLAY_AREA_OVERLAY_MODEL_DIMENSIONS.y, - z: _this.playArea.height - }) - }; - - if (_this.teleportScaleFactor < 1) { - // Adjust position of playAreOverlay so that its base is at correct height. - // Always parenting to teleport target is good enough for this. - var sensorToWorldMatrix = MyAvatar.sensorToWorldMatrix; - var sensorToWorldRotation = Mat4.extractRotation(MyAvatar.sensorToWorldMatrix); - var worldToSensorMatrix = Mat4.inverse(sensorToWorldMatrix); - var avatarSensorPosition = Mat4.transformPoint(worldToSensorMatrix, MyAvatar.position); - avatarSensorPosition.y = 0; - - var targetRotation = Overlays.getProperty(_this.targetOverlayID, "rotation"); - var relativePlayAreaCenterOffset = - Vec3.sum(_this.playAreaCenterOffset, { x: 0, y: -TARGET_MODEL_DIMENSIONS.y / 2, z: 0 }); - var localPosition = Vec3.multiplyQbyV(Quat.inverse(targetRotation), - Vec3.multiplyQbyV(sensorToWorldRotation, - Vec3.multiply(avatarScale, Vec3.subtract(relativePlayAreaCenterOffset, avatarSensorPosition)))); - localPosition.y = _this.teleportScaleFactor * localPosition.y; - - playAreaOverlayProperties.parentID = _this.targetOverlayID; - playAreaOverlayProperties.localPosition = localPosition; - } - - Overlays.editOverlay(_this.playAreaOverlay, playAreaOverlayProperties); - - for (var i = 0; i < _this.playAreaSensorPositionOverlays.length; i++) { - localPosition = _this.playAreaSensorPositions[i]; - localPosition = Vec3.multiply(avatarScale, localPosition); - // Position relative to the play area. - localPosition.y = avatarScale * (_this.PLAY_AREA_SENSOR_OVERLAY_DIMENSIONS.y / 2 - - _this.PLAY_AREA_OVERLAY_MODEL_DIMENSIONS.y / 2); - Overlays.editOverlay(_this.playAreaSensorPositionOverlays[i], { - dimensions: Vec3.multiply(_this.teleportScaleFactor * avatarScale, _this.PLAY_AREA_SENSOR_OVERLAY_DIMENSIONS), - parentID: _this.playAreaOverlay, - localPosition: localPosition - }); - } - }; - - this.updatePlayAreaScale = function () { - if (_this.isPlayAreaAvailable) { - _this.setPlayAreaDimensions(); - } - }; - - - this.teleporterSelectionName = "teleporterSelection" + hand.toString(); - this.TELEPORTER_SELECTION_STYLE = { - outlineUnoccludedColor: { red: 0, green: 0, blue: 0 }, - outlineUnoccludedAlpha: 0, - outlineOccludedColor: { red: 0, green: 0, blue: 0 }, - outlineOccludedAlpha: 0, - fillUnoccludedColor: { red: 0, green: 0, blue: 0 }, - fillUnoccludedAlpha: 0, - fillOccludedColor: { red: 0, green: 0, blue: 255 }, - fillOccludedAlpha: 0.84, - outlineWidth: 0, - isOutlineSmooth: false - }; - - this.addToSelectedItemsList = function (properties) { - for (var i = 0, length = teleportRenderStates.length; i < length; i++) { - var state = properties.renderStates[teleportRenderStates[i].name]; - if (state && state.end) { - Selection.addToSelectedItemsList(_this.teleporterSelectionName, "overlay", state.end); - } - } - }; - - - this.cleanup = function() { - Selection.removeListFromMap(_this.teleporterSelectionName); - Pointers.removePointer(_this.teleportParabolaHandVisuals); - Pointers.removePointer(_this.teleportParabolaHandCollisions); - Pointers.removePointer(_this.teleportParabolaHeadVisuals); - Pointers.removePointer(_this.teleportParabolaHeadCollisions); - Picks.removePick(_this.teleportHandCollisionPick); - Picks.removePick(_this.teleportHeadCollisionPick); - Overlays.deleteOverlay(_this.teleportedTargetOverlay); - Overlays.deleteOverlay(_this.playAreaOverlay); - for (var i = 0; i < _this.playAreaSensorPositionOverlays.length; i++) { - Overlays.deleteOverlay(_this.playAreaSensorPositionOverlays[i]); - } - _this.playAreaSensorPositionOverlays = []; - }; - - this.initPointers = function() { - if (_this.init) { - _this.cleanup(); - } - - _this.teleportParabolaHandVisuals = Pointers.createPointer(PickType.Parabola, { - joint: (_this.hand === RIGHT_HAND) ? "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" : "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", - dirOffset: { x: 0, y: 1, z: 0.1 }, - posOffset: { x: (_this.hand === RIGHT_HAND) ? 0.03 : -0.03, y: 0.2, z: 0.02 }, - filter: Picks.PICK_ENTITIES | Picks.PICK_INCLUDE_INVISIBLE, - faceAvatar: true, - scaleWithParent: true, - centerEndY: false, - speed: speed, - accelerationAxis: accelerationAxis, - rotateAccelerationWithAvatar: true, - renderStates: teleportRenderStates, - defaultRenderStates: teleportDefaultRenderStates, - maxDistance: 8.0 - }); - - _this.teleportParabolaHandCollisions = Pointers.createPointer(PickType.Parabola, { - joint: (_this.hand === RIGHT_HAND) ? "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" : "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", - dirOffset: { x: 0, y: 1, z: 0.1 }, - posOffset: { x: (_this.hand === RIGHT_HAND) ? 0.03 : -0.03, y: 0.2, z: 0.02 }, - filter: Picks.PICK_ENTITIES | Picks.PICK_INCLUDE_INVISIBLE, - faceAvatar: true, - scaleWithParent: true, - centerEndY: false, - speed: speed, - accelerationAxis: accelerationAxis, - rotateAccelerationWithAvatar: true, - renderStates: teleportRenderStates, - maxDistance: 8.0 - }); - - _this.teleportParabolaHeadVisuals = Pointers.createPointer(PickType.Parabola, { - joint: "Avatar", - filter: Picks.PICK_ENTITIES | Picks.PICK_INCLUDE_INVISIBLE, - faceAvatar: true, - scaleWithParent: true, - centerEndY: false, - speed: speed, - accelerationAxis: accelerationAxis, - rotateAccelerationWithAvatar: true, - renderStates: teleportRenderStates, - defaultRenderStates: teleportDefaultRenderStates, - maxDistance: 8.0 - }); - - _this.teleportParabolaHeadCollisions = Pointers.createPointer(PickType.Parabola, { - joint: "Avatar", - filter: Picks.PICK_ENTITIES | Picks.PICK_INCLUDE_INVISIBLE, - faceAvatar: true, - scaleWithParent: true, - centerEndY: false, - speed: speed, - accelerationAxis: accelerationAxis, - rotateAccelerationWithAvatar: true, - renderStates: teleportRenderStates, - maxDistance: 8.0 - }); - - _this.addToSelectedItemsList(Pointers.getPointerProperties(_this.teleportParabolaHandVisuals)); - _this.addToSelectedItemsList(Pointers.getPointerProperties(_this.teleportParabolaHeadVisuals)); - - - var capsuleData = MyAvatar.getCollisionCapsule(); - - var sensorToWorldScale = MyAvatar.getSensorToWorldScale(); - - var diameter = 2.0 * capsuleData.radius / sensorToWorldScale; - var height = (Vec3.distance(capsuleData.start, capsuleData.end) + diameter) / sensorToWorldScale; - var capsuleRatio = 5.0 * diameter / height; - var offset = _this.pickHeightOffset * capsuleRatio; - - _this.teleportHandCollisionPick = Picks.createPick(PickType.Collision, { - enabled: true, - parentID: Pointers.getPointerProperties(_this.teleportParabolaHandCollisions).renderStates["collision"].end, - filter: Picks.PICK_ENTITIES | Picks.PICK_AVATARS, - shape: { - shapeType: "capsule-y", - dimensions: { - x: diameter, - y: height, - z: diameter - } - }, - position: { x: 0, y: offset + height * 0.5, z: 0 }, - threshold: _this.capsuleThreshold - }); - - _this.teleportHeadCollisionPick = Picks.createPick(PickType.Collision, { - enabled: true, - parentID: Pointers.getPointerProperties(_this.teleportParabolaHeadCollisions).renderStates["collision"].end, - filter: Picks.PICK_ENTITIES | Picks.PICK_AVATARS, - shape: { - shapeType: "capsule-y", - dimensions: { - x: diameter, - y: height, - z: diameter - } - }, - position: { x: 0, y: offset + height * 0.5, z: 0 }, - threshold: _this.capsuleThreshold - }); - - - _this.playAreaOverlay = Overlays.addOverlay("model", { - url: _this.PLAY_AREA_OVERLAY_MODEL, - drawInFront: false, - visible: false - }); - - _this.teleportedTargetOverlay = Overlays.addOverlay("model", { - url: TARGET_MODEL_URL, - alpha: _this.TELEPORTED_TARGET_ALPHA, - visible: false - }); - - Selection.addToSelectedItemsList(_this.teleporterSelectionName, "overlay", _this.playAreaOverlay); - Selection.addToSelectedItemsList(_this.teleporterSelectionName, "overlay", _this.teleportedTargetOverlay); - - - _this.playArea = HMD.playArea; - _this.isPlayAreaAvailable = HMD.active && _this.playArea.width !== 0 && _this.playArea.height !== 0; - if (_this.isPlayAreaAvailable) { - _this.playAreaCenterOffset = Vec3.sum({ x: _this.playArea.x, y: 0, z: _this.playArea.y }, - _this.PLAY_AREA_OVERLAY_OFFSET); - _this.playAreaSensorPositions = HMD.sensorPositions; - - for (var i = 0; i < _this.playAreaSensorPositions.length; i++) { - if (i > _this.playAreaSensorPositionOverlays.length - 1) { - var overlay = Overlays.addOverlay("model", { - url: _this.PLAY_AREA_SENSOR_OVERLAY_MODEL, - dimensions: _this.PLAY_AREA_SENSOR_OVERLAY_DIMENSIONS, - parentID: _this.playAreaOverlay, - localRotation: _this.PLAY_AREA_SENSOR_OVERLAY_ROTATION, - drawInFront: false, - visible: false - }); - _this.playAreaSensorPositionOverlays.push(overlay); - Selection.addToSelectedItemsList(_this.teleporterSelectionName, "overlay", overlay); - } - } - - _this.setPlayAreaDimensions(); - } - - _this.init = true; - }; - - _this.initPointers(); - - - this.translateXAction = Controller.findAction("TranslateX"); - this.translateYAction = Controller.findAction("TranslateY"); - this.translateZAction = Controller.findAction("TranslateZ"); - - this.setPlayAreaVisible = function (visible, targetOverlayID, fade) { - if (!_this.isPlayAreaAvailable || _this.isPlayAreaVisible === visible) { - return; - } - - _this.wasPlayAreaVisible = _this.isPlayAreaVisible; - _this.isPlayAreaVisible = visible; - _this.targetOverlayID = targetOverlayID; - - if (_this.teleportedFadeTimer !== null) { - Script.clearTimeout(_this.teleportedFadeTimer); - _this.teleportedFadeTimer = null; - } - if (visible || !fade) { - // Immediately make visible or invisible. - _this.isPlayAreaVisible = visible; - Overlays.editOverlay(_this.playAreaOverlay, { - dimensions: Vec3.ZERO, - alpha: _this.PLAY_AREA_BOX_ALPHA, - visible: visible - }); - for (var i = 0; i < _this.playAreaSensorPositionOverlays.length; i++) { - Overlays.editOverlay(_this.playAreaSensorPositionOverlays[i], { - dimensions: Vec3.ZERO, - alpha: _this.PLAY_AREA_SENSOR_ALPHA, - visible: visible - }); - } - Overlays.editOverlay(_this.teleportedTargetOverlay, { visible: false }); - } else { - // Fading out of overlays is initiated in setTeleportVisible(). - } - }; - - this.updatePlayArea = function (position) { - var sensorToWorldMatrix = MyAvatar.sensorToWorldMatrix; - var sensorToWorldRotation = Mat4.extractRotation(MyAvatar.sensorToWorldMatrix); - var worldToSensorMatrix = Mat4.inverse(sensorToWorldMatrix); - var avatarSensorPosition = Mat4.transformPoint(worldToSensorMatrix, MyAvatar.position); - avatarSensorPosition.y = 0; - - var targetXZPosition = { x: position.x, y: 0, z: position.z }; - var avatarXZPosition = MyAvatar.position; - avatarXZPosition.y = 0; - var MIN_PARENTING_DISTANCE = 0.2; // Parenting under this distance results in the play area's rotation jittering. - if (Vec3.distance(targetXZPosition, avatarXZPosition) < MIN_PARENTING_DISTANCE) { - // Set play area position and rotation in world coordinates with no parenting. - Overlays.editOverlay(_this.playAreaOverlay, { - parentID: Uuid.NULL, - position: Vec3.sum(position, - Vec3.multiplyQbyV(sensorToWorldRotation, - Vec3.multiply(MyAvatar.sensorToWorldScale, - Vec3.subtract(_this.playAreaCenterOffset, avatarSensorPosition)))), - rotation: sensorToWorldRotation - }); - } else { - // Set play area position and rotation in local coordinates with parenting. - var targetRotation = Overlays.getProperty(_this.targetOverlayID, "rotation"); - var sensorToTargetRotation = Quat.multiply(Quat.inverse(targetRotation), sensorToWorldRotation); - var relativePlayAreaCenterOffset = - Vec3.sum(_this.playAreaCenterOffset, { x: 0, y: -TARGET_MODEL_DIMENSIONS.y / 2, z: 0 }); - Overlays.editOverlay(_this.playAreaOverlay, { - parentID: _this.targetOverlayID, - localPosition: Vec3.multiplyQbyV(Quat.inverse(targetRotation), - Vec3.multiplyQbyV(sensorToWorldRotation, - Vec3.multiply(MyAvatar.sensorToWorldScale, - Vec3.subtract(relativePlayAreaCenterOffset, avatarSensorPosition)))), - localRotation: sensorToTargetRotation - }); - } - }; - - - this.scaleInTeleport = function () { - _this.teleportScaleFactor = Math.min((Date.now() - _this.teleportScaleStart) / _this.TELEPORT_SCALE_DURATION, 1); - Pointers.editRenderState( - _this.teleportScaleMode === "head" ? _this.teleportParabolaHeadVisuals : _this.teleportParabolaHandVisuals, - "teleport", - { - path: teleportPath, // Teleport beam disappears if not included. - end: { dimensions: Vec3.multiply(_this.teleportScaleFactor, TARGET_MODEL_DIMENSIONS) } - } - ); - if (_this.isPlayAreaVisible) { - _this.setPlayAreaDimensions(); - } - if (_this.teleportScaleFactor < 1) { - _this.teleportScaleTimer = Script.setTimeout(_this.scaleInTeleport, _this.TELEPORT_SCALE_TIMEOUT); - } else { - _this.teleportScaleTimer = null; - } - }; - - this.fadeOutTeleport = function () { - var isAvatarMoving, - i, length; - - isAvatarMoving = Controller.getActionValue(_this.translateXAction) !== 0 - || Controller.getActionValue(_this.translateYAction) !== 0 - || Controller.getActionValue(_this.translateZAction) !== 0; - - if (_this.teleportedFadeDelayFactor > 0 && !_this.isTeleportVisible && !isAvatarMoving) { - // Delay fade. - _this.teleportedFadeDelayFactor = _this.teleportedFadeDelayFactor - _this.TELEPORTED_FADE_DELAY_DELTA; - _this.teleportedFadeTimer = Script.setTimeout(_this.fadeOutTeleport, _this.TELEPORTED_FADE_INTERVAL); - } else if (_this.teleportedFadeFactor > 0 && !_this.isTeleportVisible && !isAvatarMoving) { - // Fade. - _this.teleportedFadeFactor = _this.teleportedFadeFactor - _this.TELEPORTED_FADE_DELTA; - Overlays.editOverlay(_this.teleportedTargetOverlay, { - alpha: _this.teleportedFadeFactor * _this.TELEPORTED_TARGET_ALPHA - }); - if (_this.wasPlayAreaVisible) { - Overlays.editOverlay(_this.playAreaOverlay, { - alpha: _this.teleportedFadeFactor * _this.PLAY_AREA_BOX_ALPHA - }); - var sensorAlpha = _this.teleportedFadeFactor * _this.PLAY_AREA_SENSOR_ALPHA; - for (i = 0, length = _this.playAreaSensorPositionOverlays.length; i < length; i++) { - Overlays.editOverlay(_this.playAreaSensorPositionOverlays[i], { alpha: sensorAlpha }); - } - } - _this.teleportedFadeTimer = Script.setTimeout(_this.fadeOutTeleport, _this.TELEPORTED_FADE_INTERVAL); - } else { - // Make invisible. - Overlays.editOverlay(_this.teleportedTargetOverlay, { visible: false }); - if (_this.wasPlayAreaVisible) { - Overlays.editOverlay(_this.playAreaOverlay, { visible: false }); - for (i = 0, length = _this.playAreaSensorPositionOverlays.length; i < length; i++) { - Overlays.editOverlay(_this.playAreaSensorPositionOverlays[i], { visible: false }); - } - } - _this.teleportedFadeTimer = null; - Selection.disableListHighlight(_this.teleporterSelectionName); - } - }; - - this.cancelFade = function () { - // Other hand may call this to immediately hide fading overlays. - var i, length; - if (_this.teleportedFadeTimer) { - Overlays.editOverlay(_this.teleportedTargetOverlay, { visible: false }); - if (_this.wasPlayAreaVisible) { - Overlays.editOverlay(_this.playAreaOverlay, { visible: false }); - for (i = 0, length = _this.playAreaSensorPositionOverlays.length; i < length; i++) { - Overlays.editOverlay(_this.playAreaSensorPositionOverlays[i], { visible: false }); - } - } - _this.teleportedFadeTimer = null; - } - }; - - this.setTeleportVisible = function (visible, mode, fade) { - // Scales in teleport target and play area when start displaying them. - if (visible === _this.isTeleportVisible) { - return; - } - - if (visible) { - _this.teleportScaleMode = mode; - Pointers.editRenderState( - mode === "head" ? _this.teleportParabolaHeadVisuals : _this.teleportParabolaHandVisuals, - "teleport", - { - path: teleportPath, // Teleport beam disappears if not included. - end: { dimensions: Vec3.ZERO } - } - ); - _this.getOtherModule().cancelFade(); - _this.teleportScaleStart = Date.now(); - _this.teleportScaleFactor = 0; - _this.scaleInTeleport(); - Selection.enableListHighlight(_this.teleporterSelectionName, _this.TELEPORTER_SELECTION_STYLE); - } else { - if (_this.teleportScaleTimer !== null) { - Script.clearTimeout(_this.teleportScaleTimer); - _this.teleportScaleTimer = null; - } - - if (fade) { - // Copy of target at teleported position for fading. - var avatarScale = MyAvatar.sensorToWorldScale; - Overlays.editOverlay(_this.teleportedTargetOverlay, { - position: Vec3.sum(_this.teleportedPosition, { - x: 0, - y: -getAvatarFootOffset() + avatarScale * TARGET_MODEL_DIMENSIONS.y / 2, - z: 0 - }), - rotation: Quat.multiply(_this.TELEPORTED_TARGET_ROTATION, MyAvatar.orientation), - dimensions: Vec3.multiply(avatarScale, TARGET_MODEL_DIMENSIONS), - alpha: _this.TELEPORTED_TARGET_ALPHA, - visible: true - }); - - // Fade out over time. - _this.teleportedFadeDelayFactor = 1.0; - _this.teleportedFadeFactor = 1.0; - _this.teleportedFadeTimer = Script.setTimeout(_this.fadeOutTeleport, _this.TELEPORTED_FADE_DELAY); - } else { - Selection.disableListHighlight(_this.teleporterSelectionName); - } - } - - _this.isTeleportVisible = visible; - }; - - - this.axisButtonStateX = 0; // Left/right axis button pressed. - this.axisButtonStateY = 0; // Up/down axis button pressed. - this.BUTTON_TRANSITION_DELAY = 100; // Allow time for transition from direction buttons to touch-pad. - - this.axisButtonChangeX = function (value) { - if (value !== 0) { - _this.axisButtonStateX = value; - } else { - // Delay direction button release until after teleport possibly pressed. - Script.setTimeout(function () { - _this.axisButtonStateX = value; - }, _this.BUTTON_TRANSITION_DELAY); - } - }; - - this.axisButtonChangeY = function (value) { - if (value !== 0) { - _this.axisButtonStateY = value; - } else { - // Delay direction button release until after teleport possibly pressed. - Script.setTimeout(function () { - _this.axisButtonStateY = value; - }, _this.BUTTON_TRANSITION_DELAY); - } - }; - - this.teleportLocked = function () { - // Lock teleport if in advanced movement mode and have just transitioned from pressing a direction button. - return Controller.getValue(Controller.Hardware.Application.AdvancedMovement) && - (_this.axisButtonStateX !== 0 || _this.axisButtonStateY !== 0); - }; - - this.buttonPress = function (value) { - if (value === 0 || !_this.teleportLocked()) { - _this.buttonValue = value; - } - }; - - this.getStandardLY = function (value) { - _this.standardAxisLY = value; - }; - - this.getStandardRY = function (value) { - _this.standardAxisRY = value; - }; - - // Return value for the getDominantY and getOffhandY functions has to be inverted. - this.getDominantY = function () { - return (MyAvatar.getDominantHand() === "left") ? -(_this.standardAxisLY) : -(_this.standardAxisRY); - }; - - this.getOffhandY = function () { - return (MyAvatar.getDominantHand() === "left") ? -(_this.standardAxisRY) : -(_this.standardAxisLY); - }; - - this.getDominantHand = function () { - return (MyAvatar.getDominantHand() === "left") ? LEFT_HAND : RIGHT_HAND; - } - - this.getOffHand = function () { - return (MyAvatar.getDominantHand() === "left") ? RIGHT_HAND : LEFT_HAND; - } - - this.showReticle = function () { - return (_this.getDominantY() > TELEPORT_DEADZONE) ? true : false; - }; - - this.shouldTeleport = function () { - return (_this.getDominantY() > TELEPORT_DEADZONE && _this.getOffhandY() > TELEPORT_DEADZONE) ? true : false; - }; - - this.shouldCancel = function () { - //return (_this.getDominantY() < -TELEPORT_DEADZONE || _this.getOffhandY() < -TELEPORT_DEADZONE) ? true : false; - return (_this.getDominantY() <= TELEPORT_DEADZONE) ? true : false; - }; - - this.parameters = makeDispatcherModuleParameters( - 80, - this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"], - [], - 100); - - this.enterTeleport = function() { - _this.state = TELEPORTER_STATES.TARGETTING; - }; - - this.isReady = function(controllerData, deltaTime) { - if ((Window.interstitialModeEnabled && !Window.isPhysicsEnabled()) || !MyAvatar.allowTeleporting) { - return makeRunningValues(false, [], []); - } - - var otherModule = this.getOtherModule(); - if (!this.disabled && this.showReticle() && !otherModule.active && this.hand === this.getDominantHand()) { - this.active = true; - this.enterTeleport(); - return makeRunningValues(true, [], []); - } - return makeRunningValues(false, [], []); - }; - - this.run = function(controllerData, deltaTime) { - // Kill condition: - if (_this.shouldCancel()) { - _this.disableLasers(); - this.active = false; - return makeRunningValues(false, [], []); - } - - // Get current hand pose information to see if the pose is valid - var pose = Controller.getPoseValue(handInfo[(_this.hand === RIGHT_HAND) ? 'right' : 'left'].controllerInput); - var mode = pose.valid ? _this.hand : 'head'; - if (!pose.valid) { - Pointers.disablePointer(_this.teleportParabolaHandVisuals); - Pointers.disablePointer(_this.teleportParabolaHandCollisions); - Picks.disablePick(_this.teleportHandCollisionPick); - Pointers.enablePointer(_this.teleportParabolaHeadVisuals); - Pointers.enablePointer(_this.teleportParabolaHeadCollisions); - Picks.enablePick(_this.teleportHeadCollisionPick); - } else { - Pointers.enablePointer(_this.teleportParabolaHandVisuals); - Pointers.enablePointer(_this.teleportParabolaHandCollisions); - Picks.enablePick(_this.teleportHandCollisionPick); - Pointers.disablePointer(_this.teleportParabolaHeadVisuals); - Pointers.disablePointer(_this.teleportParabolaHeadCollisions); - Picks.disablePick(_this.teleportHeadCollisionPick); - } - - // We do up to 2 picks to find a teleport location. - // There are 2 types of teleport locations we are interested in: - // - // 1. A visible floor. This can be any entity surface that points within some degree of "up" - // and where the avatar capsule can be positioned without colliding - // - // 2. A seat. The seat can be visible or invisible. - // - // The Collision Pick is currently parented to the end overlay on teleportParabolaXXXXCollisions - // - // TODO - // Parent the collision Pick directly to the teleportParabolaXXXXVisuals and get rid of teleportParabolaXXXXCollisions - // - var result, collisionResult; - if (mode === 'head') { - result = Pointers.getPrevPickResult(_this.teleportParabolaHeadCollisions); - collisionResult = Picks.getPrevPickResult(_this.teleportHeadCollisionPick); - } else { - result = Pointers.getPrevPickResult(_this.teleportParabolaHandCollisions); - collisionResult = Picks.getPrevPickResult(_this.teleportHandCollisionPick); - } - - var teleportLocationType = getTeleportTargetType(result, collisionResult); - - if (teleportLocationType === TARGET.NONE) { - // Use the cancel default state - _this.setTeleportState(mode, "cancel", ""); - } else if (teleportLocationType === TARGET.INVALID) { - _this.setTeleportState(mode, "", "cancel"); - } else if (teleportLocationType === TARGET.COLLIDES) { - _this.setTeleportState(mode, "cancel", "collision"); - } else if (teleportLocationType === TARGET.SURFACE || teleportLocationType === TARGET.DISCREPANCY) { - _this.setTeleportState(mode, "teleport", "collision"); - _this.updatePlayArea(result.intersection); - } else if (teleportLocationType === TARGET.SEAT) { - _this.setTeleportState(mode, "collision", "seat"); - } - return _this.teleport(result, teleportLocationType); - }; - - this.teleport = function(newResult, target) { - var result = newResult; - _this.teleportedPosition = newResult.intersection; - if (!_this.shouldTeleport()) { - return makeRunningValues(true, [], []); - } - - if (target === TARGET.NONE || target === TARGET.INVALID) { - // Do nothing - } else if (target === TARGET.SEAT) { - Entities.callEntityMethod(result.objectID, 'sit'); - } else if (target === TARGET.SURFACE || target === TARGET.DISCREPANCY) { - var offset = getAvatarFootOffset(); - result.intersection.y += offset; - var shouldLandSafe = target === TARGET.DISCREPANCY; - MyAvatar.goToLocation(result.intersection, true, HMD.orientation, false, shouldLandSafe); - HMD.centerUI(); - MyAvatar.centerBody(); - } - - _this.disableLasers(); - _this.active = false; - return makeRunningValues(false, [], []); - }; - - this.disableLasers = function() { - _this.setPlayAreaVisible(false, null, false); - _this.setTeleportVisible(false, null, false); - Pointers.disablePointer(_this.teleportParabolaHandVisuals); - Pointers.disablePointer(_this.teleportParabolaHandCollisions); - Pointers.disablePointer(_this.teleportParabolaHeadVisuals); - Pointers.disablePointer(_this.teleportParabolaHeadCollisions); - Picks.disablePick(_this.teleportHeadCollisionPick); - Picks.disablePick(_this.teleportHandCollisionPick); - }; - - this.teleportState = ""; - - this.setTeleportState = function (mode, visibleState, invisibleState) { - var teleportState = mode + visibleState + invisibleState; - if (teleportState === _this.teleportState) { - return; - } - _this.teleportState = teleportState; - - var pointerID; - if (mode === 'head') { - Pointers.setRenderState(_this.teleportParabolaHeadVisuals, visibleState); - Pointers.setRenderState(_this.teleportParabolaHeadCollisions, invisibleState); - pointerID = _this.teleportParabolaHeadVisuals; - } else { - Pointers.setRenderState(_this.teleportParabolaHandVisuals, visibleState); - Pointers.setRenderState(_this.teleportParabolaHandCollisions, invisibleState); - pointerID = _this.teleportParabolaHandVisuals; - } - var visible = visibleState === "teleport"; - _this.setPlayAreaVisible(visible && MyAvatar.showPlayArea, - Pointers.getPointerProperties(pointerID).renderStates.teleport.end, false); - _this.setTeleportVisible(visible, mode, false); - }; - - this.setIgnoreEntities = function(entitiesToIgnore) { - Pointers.setIgnoreItems(_this.teleportParabolaHandVisuals, entitiesToIgnore); - Pointers.setIgnoreItems(_this.teleportParabolaHandCollisions, entitiesToIgnore); - Pointers.setIgnoreItems(_this.teleportParabolaHeadVisuals, entitiesToIgnore); - Pointers.setIgnoreItems(_this.teleportParabolaHeadCollisions, entitiesToIgnore); - Picks.setIgnoreItems(_this.teleportHeadCollisionPick, entitiesToIgnore); - Picks.setIgnoreItems(_this.teleportHandCollisionPick, entitiesToIgnore); - }; - } - - // related to repositioning the avatar after you teleport - var FOOT_JOINT_NAMES = ["RightToe_End", "RightToeBase", "RightFoot"]; - var DEFAULT_ROOT_TO_FOOT_OFFSET = 0.5; - - function getAvatarFootOffset() { - - // find a valid foot jointIndex - var footJointIndex = -1; - var i, l = FOOT_JOINT_NAMES.length; - for (i = 0; i < l; i++) { - footJointIndex = MyAvatar.getJointIndex(FOOT_JOINT_NAMES[i]); - if (footJointIndex !== -1) { - break; - } - } - if (footJointIndex !== -1) { - // default vertical offset from foot to avatar root. - var footPos = MyAvatar.getAbsoluteDefaultJointTranslationInObjectFrame(footJointIndex); - if (footPos.x === 0 && footPos.y === 0 && footPos.z === 0.0) { - // if footPos is exactly zero, it's probably wrong because avatar is currently loading, fall back to default. - return DEFAULT_ROOT_TO_FOOT_OFFSET * MyAvatar.scale; - } else { - return -footPos.y; - } - } else { - return DEFAULT_ROOT_TO_FOOT_OFFSET * MyAvatar.scale; - } - } - - var mappingName, teleportMapping; - var isViveMapped = false; - - function parseJSON(json) { - try { - return JSON.parse(json); - } catch (e) { - return undefined; - } - } - // When determininig whether you can teleport to a location, the normal of the - // point that is being intersected with is looked at. If this normal is more - // than MAX_ANGLE_FROM_UP_TO_TELEPORT degrees from your avatar's up, then - // you can't teleport there. - var MAX_ANGLE_FROM_UP_TO_TELEPORT = 70; - var MAX_DISCREPANCY_DISTANCE = 1.0; - var MAX_DOT_SIGN = -0.6; - - function checkForMeshDiscrepancy(result, collisionResult) { - var intersectingObjects = collisionResult.intersectingObjects; - if (intersectingObjects.length > 0 && intersectingObjects.length < 3) { - for (var j = 0; j < collisionResult.intersectingObjects.length; j++) { - var intersectingObject = collisionResult.intersectingObjects[j]; - for (var i = 0; i < intersectingObject.collisionContacts.length; i++) { - var normal = intersectingObject.collisionContacts[i].normalOnPick; - var distanceToPick = Vec3.distance(intersectingObject.collisionContacts[i].pointOnPick, result.intersection); - var normalSign = Vec3.dot(normal, Quat.getUp(MyAvatar.orientation)); - if ((distanceToPick > MAX_DISCREPANCY_DISTANCE) || (normalSign > MAX_DOT_SIGN)) { - return false; - } - } - } - return true; - } - return false; - } - - function getTeleportTargetType(result, collisionResult) { - if (result.type === Picks.INTERSECTED_NONE) { - return TARGET.NONE; - } - - var props = Entities.getEntityProperties(result.objectID, ['userData', 'visible']); - var data = parseJSON(props.userData); - if (data !== undefined && data.seat !== undefined) { - var avatarUuid = Uuid.fromString(data.seat.user); - if (Uuid.isNull(avatarUuid) || !AvatarList.getAvatar(avatarUuid).sessionUUID) { - return TARGET.SEAT; - } else { - return TARGET.INVALID; - } - } - var isDiscrepancy = false; - if (collisionResult.collisionRegion != undefined) { - if (collisionResult.intersects) { - isDiscrepancy = checkForMeshDiscrepancy(result, collisionResult); - if (!isDiscrepancy) { - return TARGET.COLLIDES; - } - } - } - - var surfaceNormal = result.surfaceNormal; - var angle = Math.acos(Vec3.dot(surfaceNormal, Quat.getUp(MyAvatar.orientation))) * (180.0 / Math.PI); - - if (angle > MAX_ANGLE_FROM_UP_TO_TELEPORT) { - return TARGET.INVALID; - } else if (isDiscrepancy) { - return TARGET.DISCREPANCY; - } else { - return TARGET.SURFACE; - } - } - - function registerViveTeleportMapping() { - // Disable Vive teleport if touch is transitioning across touch-pad after pressing a direction button. - if (Controller.Hardware.Vive) { - var mappingName = 'Hifi-Teleporter-Dev-Vive-' + Math.random(); - var viveTeleportMapping = Controller.newMapping(mappingName); - viveTeleportMapping.from(Controller.Hardware.Vive.LSX).peek().to(leftTeleporter.axisButtonChangeX); - viveTeleportMapping.from(Controller.Hardware.Vive.LSY).peek().to(leftTeleporter.axisButtonChangeY); - viveTeleportMapping.from(Controller.Hardware.Vive.RSX).peek().to(rightTeleporter.axisButtonChangeX); - viveTeleportMapping.from(Controller.Hardware.Vive.RSY).peek().to(rightTeleporter.axisButtonChangeY); - Controller.enableMapping(mappingName); - isViveMapped = true; - } - } - - function onHardwareChanged() { - // Controller.Hardware.Vive is not immediately available at Interface start-up. - if (!isViveMapped && Controller.Hardware.Vive) { - registerViveTeleportMapping(); - } - } - - Controller.hardwareChanged.connect(onHardwareChanged); - - function registerMappings() { - mappingName = 'Hifi-Teleporter-Dev-' + Math.random(); - teleportMapping = Controller.newMapping(mappingName); - - // Vive teleport button lock-out. - registerViveTeleportMapping(); - - // Teleport actions. - teleportMapping.from(Controller.Standard.LeftPrimaryThumb).peek().to(leftTeleporter.buttonPress); - teleportMapping.from(Controller.Standard.RightPrimaryThumb).peek().to(rightTeleporter.buttonPress); - teleportMapping.from(Controller.Standard.LY).peek().to(leftTeleporter.getStandardLY); - teleportMapping.from(Controller.Standard.RY).peek().to(leftTeleporter.getStandardRY); - teleportMapping.from(Controller.Standard.LY).peek().to(rightTeleporter.getStandardLY); - teleportMapping.from(Controller.Standard.RY).peek().to(rightTeleporter.getStandardRY); - } - - var leftTeleporter = new Teleporter(LEFT_HAND); - var rightTeleporter = new Teleporter(RIGHT_HAND); - - enableDispatcherModule("LeftTeleporter", leftTeleporter); - enableDispatcherModule("RightTeleporter", rightTeleporter); - registerMappings(); - Controller.enableMapping(mappingName); - - function cleanup() { - Controller.hardwareChanged.disconnect(onHardwareChanged); - teleportMapping.disable(); - leftTeleporter.cleanup(); - rightTeleporter.cleanup(); - disableDispatcherModule("LeftTeleporter"); - disableDispatcherModule("RightTeleporter"); - } - Script.scriptEnding.connect(cleanup); - - var handleTeleportMessages = function(channel, message, sender) { - if (sender === MyAvatar.sessionUUID) { - if (channel === 'Hifi-Teleport-Disabler') { - if (message === 'both') { - leftTeleporter.disabled = true; - rightTeleporter.disabled = true; - } - if (message === 'left') { - leftTeleporter.disabled = true; - rightTeleporter.disabled = false; - } - if (message === 'right') { - leftTeleporter.disabled = false; - rightTeleporter.disabled = true; - } - if (message === 'none') { - leftTeleporter.disabled = false; - rightTeleporter.disabled = false; - } - } else if (channel === 'Hifi-Teleport-Ignore-Add' && - !Uuid.isNull(message) && - ignoredEntities.indexOf(message) === -1) { - ignoredEntities.push(message); - leftTeleporter.setIgnoreEntities(ignoredEntities); - rightTeleporter.setIgnoreEntities(ignoredEntities); - } else if (channel === 'Hifi-Teleport-Ignore-Remove' && !Uuid.isNull(message)) { - var removeIndex = ignoredEntities.indexOf(message); - if (removeIndex > -1) { - ignoredEntities.splice(removeIndex, 1); - leftTeleporter.setIgnoreEntities(ignoredEntities); - rightTeleporter.setIgnoreEntities(ignoredEntities); - } - } - } - }; - - MyAvatar.onLoadComplete.connect(function () { - Script.setTimeout(function () { - leftTeleporter.initPointers(); - rightTeleporter.initPointers(); - }, 500); - }); - - Messages.subscribe('Hifi-Teleport-Disabler'); - Messages.subscribe('Hifi-Teleport-Ignore-Add'); - Messages.subscribe('Hifi-Teleport-Ignore-Remove'); - Messages.messageReceived.connect(handleTeleportMessages); - - MyAvatar.sensorToWorldScaleChanged.connect(function () { - leftTeleporter.updatePlayAreaScale(); - rightTeleporter.updatePlayAreaScale(); - }); - -}()); // END LOCAL_SCOPE diff --git a/scripts/simplifiedUI/system/controllers/controllerModules/webSurfaceLaserInput.js b/scripts/simplifiedUI/system/controllers/controllerModules/webSurfaceLaserInput.js deleted file mode 100644 index cf700a8ad9..0000000000 --- a/scripts/simplifiedUI/system/controllers/controllerModules/webSurfaceLaserInput.js +++ /dev/null @@ -1,288 +0,0 @@ -"use strict"; - -// webSurfaceLaserInput.js -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - -/* global Script, Entities, enableDispatcherModule, disableDispatcherModule, makeRunningValues, - makeDispatcherModuleParameters, Overlays, HMD, TRIGGER_ON_VALUE, TRIGGER_OFF_VALUE, getEnabledModuleByName, - ContextOverlay, Picks, makeLaserParams, Settings, MyAvatar, RIGHT_HAND, LEFT_HAND, DISPATCHER_PROPERTIES -*/ - -Script.include("/~/system/libraries/controllerDispatcherUtils.js"); -Script.include("/~/system/libraries/controllers.js"); - -(function() { - const intersectionType = { - None: 0, - WebOverlay: 1, - WebEntity: 2, - HifiKeyboard: 3, - Overlay: 4, - HifiTablet: 5, - }; - - function WebSurfaceLaserInput(hand) { - this.hand = hand; - this.otherHand = this.hand === RIGHT_HAND ? LEFT_HAND : RIGHT_HAND; - this.running = false; - this.ignoredObjects = []; - this.intersectedType = intersectionType["None"]; - - this.parameters = makeDispatcherModuleParameters( - 160, - this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"], - [], - 100, - makeLaserParams(hand, true)); - - this.getFarGrab = function () { - return getEnabledModuleByName(this.hand === RIGHT_HAND ? ("RightFarGrabEntity") : ("LeftFarGrabEntity")); - }; - - this.farGrabActive = function () { - var farGrab = this.getFarGrab(); - // farGrab will be null if module isn't loaded. - if (farGrab) { - return farGrab.targetIsNull(); - } else { - return false; - } - }; - - this.grabModuleWantsNearbyOverlay = function(controllerData) { - if (controllerData.triggerValues[this.hand] > TRIGGER_ON_VALUE || controllerData.secondaryValues[this.hand] > BUMPER_ON_VALUE) { - var nearGrabName = this.hand === RIGHT_HAND ? "RightNearParentingGrabOverlay" : "LeftNearParentingGrabOverlay"; - var nearGrabModule = getEnabledModuleByName(nearGrabName); - if (nearGrabModule) { - var candidateOverlays = controllerData.nearbyOverlayIDs[this.hand]; - var grabbableOverlays = candidateOverlays.filter(function(overlayID) { - return Overlays.getProperty(overlayID, "grabbable"); - }); - var target = nearGrabModule.getTargetID(grabbableOverlays, controllerData); - if (target) { - return true; - } - } - nearGrabName = this.hand === RIGHT_HAND ? "RightNearParentingGrabEntity" : "LeftNearParentingGrabEntity"; - nearGrabModule = getEnabledModuleByName(nearGrabName); - if (nearGrabModule && nearGrabModule.isReady(controllerData)) { - // check for if near parent module is active. - var isNearGrabModuleActive = nearGrabModule.isReady(controllerData).active; - if (isNearGrabModuleActive) { - // if true, return true. - return isNearGrabModuleActive; - } else { - // check near action grab entity as a second pass. - nearGrabName = this.hand === RIGHT_HAND ? "RightNearActionGrabEntity" : "LeftNearActionGrabEntity"; - nearGrabModule = getEnabledModuleByName(nearGrabName); - if (nearGrabModule && nearGrabModule.isReady(controllerData)) { - return nearGrabModule.isReady(controllerData).active; - } - } - } - } - - var nearTabletHighlightModule = getEnabledModuleByName(this.hand === RIGHT_HAND - ? "RightNearTabletHighlight" : "LeftNearTabletHighlight"); - if (nearTabletHighlightModule) { - return nearTabletHighlightModule.isNearTablet(controllerData); - } - - return false; - }; - - this.getOtherModule = function() { - return this.hand === RIGHT_HAND ? leftOverlayLaserInput : rightOverlayLaserInput; - }; - - this.addObjectToIgnoreList = function(controllerData) { - if (Window.interstitialModeEnabled && !Window.isPhysicsEnabled()) { - var intersection = controllerData.rayPicks[this.hand]; - var objectID = intersection.objectID; - - if (intersection.type === Picks.INTERSECTED_OVERLAY) { - var overlayIndex = this.ignoredObjects.indexOf(objectID); - - var overlayName = Overlays.getProperty(objectID, "name"); - if (overlayName !== "Loading-Destination-Card-Text" && overlayName !== "Loading-Destination-Card-GoTo-Image" && - overlayName !== "Loading-Destination-Card-GoTo-Image-Hover") { - var data = { - action: 'add', - id: objectID - }; - Messages.sendMessage('Hifi-Hand-RayPick-Blacklist', JSON.stringify(data)); - this.ignoredObjects.push(objectID); - } - } else if (intersection.type === Picks.INTERSECTED_ENTITY) { - var entityIndex = this.ignoredObjects.indexOf(objectID); - var data = { - action: 'add', - id: objectID - }; - Messages.sendMessage('Hifi-Hand-RayPick-Blacklist', JSON.stringify(data)); - this.ignoredObjects.push(objectID); - } - } - }; - - this.restoreIgnoredObjects = function() { - for (var index = 0; index < this.ignoredObjects.length; index++) { - var data = { - action: 'remove', - id: this.ignoredObjects[index] - }; - Messages.sendMessage('Hifi-Hand-RayPick-Blacklist', JSON.stringify(data)); - } - - this.ignoredObjects = []; - }; - - this.getInteractableType = function(controllerData, triggerPressed, checkEntitiesOnly) { - // allow pointing at tablet, unlocked web entities, or web overlays automatically without pressing trigger, - // but for pointing at locked web entities or non-web overlays user must be pressing trigger - var intersection = controllerData.rayPicks[this.hand]; - var objectID = intersection.objectID; - if (intersection.type === Picks.INTERSECTED_OVERLAY && !checkEntitiesOnly) { - if ((HMD.tabletID && objectID === HMD.tabletID) || - (HMD.tabletScreenID && objectID === HMD.tabletScreenID) || - (HMD.homeButtonID && objectID === HMD.homeButtonID)) { - return intersectionType["HifiTablet"]; - } else { - var overlayType = Overlays.getOverlayType(objectID); - var type = intersectionType["None"]; - if (Keyboard.containsID(objectID) && !Keyboard.preferMalletsOverLasers) { - type = intersectionType["HifiKeyboard"]; - } else if (overlayType === "web3d") { - type = intersectionType["WebOverlay"]; - } else if (triggerPressed) { - type = intersectionType["Overlay"]; - } - - return type; - } - } else if (intersection.type === Picks.INTERSECTED_ENTITY) { - var entityProperties = Entities.getEntityProperties(objectID, DISPATCHER_PROPERTIES); - var entityType = entityProperties.type; - var isLocked = entityProperties.locked; - if (entityType === "Web" && (!isLocked || triggerPressed)) { - return intersectionType["WebEntity"]; - } - } - return intersectionType["None"]; - }; - - this.deleteContextOverlay = function() { - var farGrabModule = getEnabledModuleByName(this.hand === RIGHT_HAND ? - "RightFarActionGrabEntity" : - "LeftFarActionGrabEntity"); - if (farGrabModule) { - var entityWithContextOverlay = farGrabModule.entityWithContextOverlay; - - if (entityWithContextOverlay) { - ContextOverlay.destroyContextOverlay(entityWithContextOverlay); - farGrabModule.entityWithContextOverlay = false; - } - } - }; - - this.updateAlwaysOn = function(type) { - var PREFER_STYLUS_OVER_LASER = "preferStylusOverLaser"; - this.parameters.handLaser.alwaysOn = (!Settings.getValue(PREFER_STYLUS_OVER_LASER, false) || type === intersectionType["HifiKeyboard"]); - }; - - this.getDominantHand = function() { - return MyAvatar.getDominantHand() === "right" ? 1 : 0; - }; - - this.dominantHandOverride = false; - - this.isReady = function (controllerData) { - // Trivial rejection for when FarGrab is active. - if (this.farGrabActive()) { - return makeRunningValues(false, [], []); - } - - var isTriggerPressed = controllerData.triggerValues[this.hand] > TRIGGER_OFF_VALUE && - controllerData.triggerValues[this.otherHand] <= TRIGGER_OFF_VALUE; - var type = this.getInteractableType(controllerData, isTriggerPressed, false); - - if (type !== intersectionType["None"] && !this.grabModuleWantsNearbyOverlay(controllerData)) { - if (type === intersectionType["WebOverlay"] || type === intersectionType["WebEntity"] || type === intersectionType["HifiTablet"]) { - var otherModuleRunning = this.getOtherModule().running; - otherModuleRunning = otherModuleRunning && this.getDominantHand() !== this.hand; // Auto-swap to dominant hand. - var allowThisModule = !otherModuleRunning || isTriggerPressed; - - if (!allowThisModule) { - return makeRunningValues(true, [], []); - } - - if (isTriggerPressed) { - this.dominantHandOverride = true; // Override dominant hand. - this.getOtherModule().dominantHandOverride = false; - } - } - - this.updateAlwaysOn(type); - if (this.parameters.handLaser.alwaysOn || isTriggerPressed) { - return makeRunningValues(true, [], []); - } - } - - if (Window.interstitialModeEnabled && Window.isPhysicsEnabled()) { - this.restoreIgnoredObjects(); - } - return makeRunningValues(false, [], []); - }; - - this.shouldThisModuleRun = function(controllerData) { - var otherModuleRunning = this.getOtherModule().running; - otherModuleRunning = otherModuleRunning && this.getDominantHand() !== this.hand; // Auto-swap to dominant hand. - otherModuleRunning = otherModuleRunning || this.getOtherModule().dominantHandOverride; // Override dominant hand. - var grabModuleNeedsToRun = this.grabModuleWantsNearbyOverlay(controllerData); - // only allow for non-near grab - return !otherModuleRunning && !grabModuleNeedsToRun; - }; - - this.run = function(controllerData, deltaTime) { - this.addObjectToIgnoreList(controllerData); - var isTriggerPressed = controllerData.triggerValues[this.hand] > TRIGGER_OFF_VALUE; - var type = this.getInteractableType(controllerData, isTriggerPressed, false); - var laserOn = isTriggerPressed || this.parameters.handLaser.alwaysOn; - this.addObjectToIgnoreList(controllerData); - - if (type === intersectionType["HifiTablet"] && laserOn) { - if (this.shouldThisModuleRun(controllerData)) { - this.running = true; - return makeRunningValues(true, [], []); - } - } else if ((type === intersectionType["WebOverlay"] || type === intersectionType["WebEntity"]) && laserOn) { // auto laser on WebEntities andWebOverlays - if (this.shouldThisModuleRun(controllerData)) { - this.running = true; - return makeRunningValues(true, [], []); - } - } else if ((type === intersectionType["HifiKeyboard"] && laserOn) || type === intersectionType["Overlay"]) { - this.running = true; - return makeRunningValues(true, [], []); - } - - this.deleteContextOverlay(); - this.running = false; - this.dominantHandOverride = false; - return makeRunningValues(false, [], []); - }; - } - - var leftOverlayLaserInput = new WebSurfaceLaserInput(LEFT_HAND); - var rightOverlayLaserInput = new WebSurfaceLaserInput(RIGHT_HAND); - - enableDispatcherModule("LeftWebSurfaceLaserInput", leftOverlayLaserInput); - enableDispatcherModule("RightWebSurfaceLaserInput", rightOverlayLaserInput); - - function cleanup() { - disableDispatcherModule("LeftWebSurfaceLaserInput"); - disableDispatcherModule("RightWebSurfaceLaserInput"); - } - Script.scriptEnding.connect(cleanup); -}()); diff --git a/scripts/simplifiedUI/system/controllers/controllerScripts.js b/scripts/simplifiedUI/system/controllers/controllerScripts.js deleted file mode 100644 index c9cb61b5f5..0000000000 --- a/scripts/simplifiedUI/system/controllers/controllerScripts.js +++ /dev/null @@ -1,62 +0,0 @@ -"use strict"; - -// controllerScripts.js -// -// Created by David Rowe on 15 Mar 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 -// - -/* global Script, Menu */ - -var CONTOLLER_SCRIPTS = [ - "squeezeHands.js", - "controllerDisplayManager.js", - "grab.js", - //"toggleAdvancedMovementForHandControllers.js", - "handTouch.js", - "controllerDispatcher.js", - "controllerModules/nearParentGrabOverlay.js", - "controllerModules/stylusInput.js", - "controllerModules/equipEntity.js", - "controllerModules/nearTrigger.js", - "controllerModules/webSurfaceLaserInput.js", - "controllerModules/inEditMode.js", - "controllerModules/inVREditMode.js", - "controllerModules/disableOtherModule.js", - "controllerModules/farTrigger.js", - "controllerModules/teleport.js", - "controllerModules/hudOverlayPointer.js", - "controllerModules/mouseHMD.js", - "controllerModules/nearGrabHyperLinkEntity.js", - "controllerModules/nearTabletHighlight.js", - "controllerModules/nearGrabEntity.js", - "controllerModules/farGrabEntity.js", - "controllerModules/pushToTalk.js" -]; - -var DEBUG_MENU_ITEM = "Debug defaultScripts.js"; - -function runDefaultsTogether() { - for (var j in CONTOLLER_SCRIPTS) { - if (CONTOLLER_SCRIPTS.hasOwnProperty(j)) { - Script.include(CONTOLLER_SCRIPTS[j]); - } - } -} - -function runDefaultsSeparately() { - for (var i in CONTOLLER_SCRIPTS) { - if (CONTOLLER_SCRIPTS.hasOwnProperty(i)) { - Script.load(CONTOLLER_SCRIPTS[i]); - } - } -} - -if (Menu.isOptionChecked(DEBUG_MENU_ITEM)) { - runDefaultsSeparately(); -} else { - runDefaultsTogether(); -} diff --git a/scripts/simplifiedUI/system/controllers/godView.js b/scripts/simplifiedUI/system/controllers/godView.js deleted file mode 100644 index 4b406399fd..0000000000 --- a/scripts/simplifiedUI/system/controllers/godView.js +++ /dev/null @@ -1,116 +0,0 @@ -"use strict"; -// -// godView.js -// scripts/system/ -// -// Created by Brad Hefta-Gaub on 1 Jun 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 -// -/* globals HMD, Script, Menu, Tablet, Camera */ -/* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ - -(function() { // BEGIN LOCAL_SCOPE - -var godView = false; - -var GOD_CAMERA_OFFSET = -1; // 1 meter below the avatar -var GOD_VIEW_HEIGHT = 300; // 300 meter above the ground -var ABOVE_GROUND_DROP = 2; -var MOVE_BY = 1; - -function moveTo(position) { - if (godView) { - MyAvatar.position = position; - Camera.position = Vec3.sum(MyAvatar.position, {x:0, y: GOD_CAMERA_OFFSET, z: 0}); - } else { - MyAvatar.position = position; - } -} - -function keyPressEvent(event) { - if (godView) { - switch(event.text) { - case "UP": - moveTo(Vec3.sum(MyAvatar.position, {x:0.0, y: 0, z: -1 * MOVE_BY})); - break; - case "DOWN": - moveTo(Vec3.sum(MyAvatar.position, {x:0, y: 0, z: MOVE_BY})); - break; - case "LEFT": - moveTo(Vec3.sum(MyAvatar.position, {x:-1 * MOVE_BY, y: 0, z: 0})); - break; - case "RIGHT": - moveTo(Vec3.sum(MyAvatar.position, {x:MOVE_BY, y: 0, z: 0})); - break; - } - } -} - -function mousePress(event) { - if (godView) { - var pickRay = Camera.computePickRay(event.x, event.y); - var pointingAt = Vec3.sum(pickRay.origin, Vec3.multiply(pickRay.direction,300)); - var moveToPosition = { x: pointingAt.x, y: MyAvatar.position.y, z: pointingAt.z }; - moveTo(moveToPosition); - } -} - - -var oldCameraMode = Camera.mode; - -function startGodView() { - if (!godView) { - oldCameraMode = Camera.mode; - MyAvatar.position = Vec3.sum(MyAvatar.position, {x:0, y: GOD_VIEW_HEIGHT, z: 0}); - Camera.mode = "independent"; - Camera.position = Vec3.sum(MyAvatar.position, {x:0, y: GOD_CAMERA_OFFSET, z: 0}); - Camera.orientation = Quat.fromPitchYawRollDegrees(-90,0,0); - godView = true; - } -} - -function endGodView() { - if (godView) { - Camera.mode = oldCameraMode; - MyAvatar.position = Vec3.sum(MyAvatar.position, {x:0, y: (-1 * GOD_VIEW_HEIGHT) + ABOVE_GROUND_DROP, z: 0}); - godView = false; - } -} - -var button; -var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - -function onClicked() { - if (godView) { - endGodView(); - } else { - startGodView(); - } -} - -button = tablet.addButton({ - icon: "icons/tablet-icons/switch-desk-i.svg", // FIXME - consider a better icon from Alan - text: "God View" -}); - -button.clicked.connect(onClicked); -Controller.keyPressEvent.connect(keyPressEvent); -Controller.mousePressEvent.connect(mousePress); - - -Script.scriptEnding.connect(function () { - if (godView) { - endGodView(); - } - button.clicked.disconnect(onClicked); - if (tablet) { - tablet.removeButton(button); - } - Controller.keyPressEvent.disconnect(keyPressEvent); - Controller.mousePressEvent.disconnect(mousePress); -}); - -}()); // END LOCAL_SCOPE diff --git a/scripts/simplifiedUI/system/controllers/grab.js b/scripts/simplifiedUI/system/controllers/grab.js deleted file mode 100644 index 1fb82d3843..0000000000 --- a/scripts/simplifiedUI/system/controllers/grab.js +++ /dev/null @@ -1,522 +0,0 @@ -"use strict"; - -// grab.js -// examples -// -// Created by Eric Levin on May 1, 2015 -// Copyright 2015 High Fidelity, Inc. -// -// Grab's physically moveable entities with the mouse, by applying a spring force. -// -// Updated November 22, 2016 by Philip Rosedale: Add distance attenuation of grab effect -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -/* global MyAvatar, Entities, Script, HMD, Camera, Vec3, Reticle, Overlays, Messages, Quat, Controller, - isInEditMode, entityIsGrabbable, Picks, PickType, Pointers, unhighlightTargetEntity, DISPATCHER_PROPERTIES, - entityIsGrabbable, getMainTabletIDs -*/ -/* jslint bitwise: true */ - -(function() { // BEGIN LOCAL_SCOPE - -Script.include("/~/system/libraries/utils.js"); -Script.include("/~/system/libraries/controllerDispatcherUtils.js"); - -var MOUSE_GRAB_JOINT = 65526; // FARGRAB_MOUSE_INDEX - -var MAX_SOLID_ANGLE = 0.01; // objects that appear smaller than this can't be grabbed - -var DELAY_FOR_30HZ = 33; // milliseconds - -var ZERO_VEC3 = { x: 0, y: 0, z: 0 }; -var IDENTITY_QUAT = { x: 0, y: 0, z: 0, w: 1 }; - -// helper function -function mouseIntersectionWithPlane(pointOnPlane, planeNormal, event, maxDistance) { - var cameraPosition = Camera.getPosition(); - var localPointOnPlane = Vec3.subtract(pointOnPlane, cameraPosition); - var distanceFromPlane = Vec3.dot(localPointOnPlane, planeNormal); - var MIN_DISTANCE_FROM_PLANE = 0.001; - if (Math.abs(distanceFromPlane) < MIN_DISTANCE_FROM_PLANE) { - // camera is touching the plane - return pointOnPlane; - } - var pickRay = Camera.computePickRay(event.x, event.y); - var dirDotNorm = Vec3.dot(pickRay.direction, planeNormal); - var MIN_RAY_PLANE_DOT = 0.00001; - - var localIntersection; - var useMaxForwardGrab = false; - if (Math.abs(dirDotNorm) > MIN_RAY_PLANE_DOT) { - var distanceToIntersection = distanceFromPlane / dirDotNorm; - if (distanceToIntersection > 0 && distanceToIntersection < maxDistance) { - // ray points into the plane - localIntersection = Vec3.multiply(pickRay.direction, distanceFromPlane / dirDotNorm); - } else { - // ray intersects BEHIND the camera or else very far away - // so we clamp the grab point to be the maximum forward position - useMaxForwardGrab = true; - } - } else { - // ray points perpendicular to grab plane - // so we map the grab point to the maximum forward position - useMaxForwardGrab = true; - } - if (useMaxForwardGrab) { - // we re-route the intersection to be in front at max distance. - var rayDirection = Vec3.subtract(pickRay.direction, Vec3.multiply(planeNormal, dirDotNorm)); - rayDirection = Vec3.normalize(rayDirection); - localIntersection = Vec3.multiply(rayDirection, maxDistance); - localIntersection = Vec3.sum(localIntersection, Vec3.multiply(planeNormal, distanceFromPlane)); - } - var worldIntersection = Vec3.sum(cameraPosition, localIntersection); - return worldIntersection; -} - -// Mouse class stores mouse click and drag info -function Mouse() { - this.current = { - x: 0, - y: 0 - }; - this.previous = { - x: 0, - y: 0 - }; - this.rotateStart = { - x: 0, - y: 0 - }; - this.cursorRestore = { - x: 0, - y: 0 - }; -} - -Mouse.prototype.startDrag = function(position) { - this.current = { - x: position.x, - y: position.y - }; - this.startRotateDrag(); -}; - -Mouse.prototype.updateDrag = function(position) { - this.current = { - x: position.x, - y: position.y - }; -}; - -Mouse.prototype.startRotateDrag = function() { - this.previous = { - x: this.current.x, - y: this.current.y - }; - this.rotateStart = { - x: this.current.x, - y: this.current.y - }; - this.cursorRestore = Reticle.getPosition(); -}; - -Mouse.prototype.getDrag = function() { - var delta = { - x: this.current.x - this.previous.x, - y: this.current.y - this.previous.y - }; - this.previous = { - x: this.current.x, - y: this.current.y - }; - return delta; -}; - -Mouse.prototype.restoreRotateCursor = function() { - Reticle.setPosition(this.cursorRestore); - this.current = { - x: this.rotateStart.x, - y: this.rotateStart.y - }; -}; - -var mouse = new Mouse(); - -var beacon = { - type: "cube", - dimensions: { - x: 0.01, - y: 0, - z: 0.01 - }, - color: { - red: 200, - green: 200, - blue: 200 - }, - alpha: 1, - solid: true, - ignoreRayIntersection: true, - visible: true -}; - -// TODO: play sounds again when we aren't leaking AudioInjector threads -// var grabSound = SoundCache.getSound("https://hifi-public.s3.amazonaws.com/eric/sounds/CloseClamp.wav"); -// var releaseSound = SoundCache.getSound("https://hifi-public.s3.amazonaws.com/eric/sounds/ReleaseClamp.wav"); -// var VOLUME = 0.0; - - -// Grabber class stores and computes info for grab behavior -function Grabber() { - this.isGrabbing = false; - this.entityID = null; - this.startPosition = ZERO_VEC3; - this.lastRotation = IDENTITY_QUAT; - this.currentPosition = ZERO_VEC3; - this.planeNormal = ZERO_VEC3; - - // maxDistance is a function of the size of the object. - this.maxDistance = 0; - - // mode defines the degrees of freedom of the grab target positions - // relative to startPosition options include: - // xzPlane (default) - // verticalCylinder (SHIFT) - // rotate (CONTROL) - this.mode = "xzplane"; - - // offset allows the user to grab an object off-center. It points from the object's center - // to the point where the ray intersects the grab plane (at the moment the grab is initiated). - // Future target positions of the ray intersection are on the same plane, and the offset is subtracted - // to compute the target position of the object's center. - this.offset = { - x: 0, - y: 0, - z: 0 - }; - - this.liftKey = false; // SHIFT - this.rotateKey = false; // CONTROL - - this.mouseRayOverlays = Picks.createPick(PickType.Ray, { - joint: "Mouse", - filter: Picks.PICK_OVERLAYS | Picks.PICK_INCLUDE_NONCOLLIDABLE, - enabled: true - }); - var tabletItems = getMainTabletIDs(); - if (tabletItems.length > 0) { - Picks.setIncludeItems(this.mouseRayOverlays, tabletItems); - } - var renderStates = [{name: "grabbed", end: beacon}]; - this.mouseRayEntities = Pointers.createPointer(PickType.Ray, { - joint: "Mouse", - filter: Picks.PICK_ENTITIES | Picks.PICK_INCLUDE_NONCOLLIDABLE, - faceAvatar: true, - scaleWithParent: true, - enabled: true, - renderStates: renderStates - }); -} - -Grabber.prototype.computeNewGrabPlane = function() { - if (!this.isGrabbing) { - return; - } - - var modeWasRotate = (this.mode == "rotate"); - this.mode = "xzPlane"; - this.planeNormal = { - x: 0, - y: 1, - z: 0 - }; - if (this.rotateKey) { - this.mode = "rotate"; - mouse.startRotateDrag(); - } else { - if (modeWasRotate) { - // we reset the mouse screen position whenever we stop rotating - mouse.restoreRotateCursor(); - } - if (this.liftKey) { - this.mode = "verticalCylinder"; - // NOTE: during verticalCylinder mode a new planeNormal will be computed each move - } - } - - this.pointOnPlane = Vec3.subtract(this.currentPosition, this.offset); - var xzOffset = Vec3.subtract(this.pointOnPlane, Camera.getPosition()); - xzOffset.y = 0; - this.xzDistanceToGrab = Vec3.length(xzOffset); -}; - -Grabber.prototype.pressEvent = function(event) { - if (isInEditMode() || HMD.active) { - return; - } - if (event.button !== "LEFT") { - return; - } - if (event.isAlt || event.isMeta) { - return; - } - if (Overlays.getOverlayAtPoint(Reticle.position) > 0) { - // the mouse is pointing at an overlay; don't look for entities underneath the overlay. - return; - } - - var overlayResult = Picks.getPrevPickResult(this.mouseRayOverlays); - if (overlayResult.type != Picks.INTERSECTED_NONE) { - return; - } - - var pickResults = Pointers.getPrevPickResult(this.mouseRayEntities); - if (pickResults.type == Picks.INTERSECTED_NONE) { - Pointers.setRenderState(this.mouseRayEntities, ""); - return; - } - - var props = Entities.getEntityProperties(pickResults.objectID, DISPATCHER_PROPERTIES); - if (!entityIsGrabbable(props)) { - // only grab grabbable objects - return; - } - if (props.grab.equippable) { - // don't mouse-grab click-to-equip entities (let equipEntity.js handle these) - return; - } - - Pointers.setRenderState(this.mouseRayEntities, "grabbed"); - Pointers.setLockEndUUID(this.mouseRayEntities, pickResults.objectID, false); - unhighlightTargetEntity(pickResults.objectID); - - mouse.startDrag(event); - - var clickedEntity = pickResults.objectID; - var entityProperties = Entities.getEntityProperties(clickedEntity, DISPATCHER_PROPERTIES); - this.startPosition = entityProperties.position; - this.lastRotation = entityProperties.rotation; - var cameraPosition = Camera.getPosition(); - - var objectBoundingDiameter = Vec3.length(entityProperties.dimensions); - beacon.dimensions.y = objectBoundingDiameter; - Pointers.editRenderState(this.mouseRayEntities, "grabbed", {end: beacon}); - this.maxDistance = objectBoundingDiameter / MAX_SOLID_ANGLE; - if (Vec3.distance(this.startPosition, cameraPosition) > this.maxDistance) { - // don't allow grabs of things far away - return; - } - - this.isGrabbing = true; - - this.entityID = clickedEntity; - this.currentPosition = entityProperties.position; - - // compute the grab point - var pickRay = Camera.computePickRay(event.x, event.y); - var nearestPoint = Vec3.subtract(this.startPosition, cameraPosition); - var distanceToGrab = Vec3.dot(nearestPoint, pickRay.direction); - nearestPoint = Vec3.multiply(distanceToGrab, pickRay.direction); - this.pointOnPlane = Vec3.sum(cameraPosition, nearestPoint); - - // compute the grab offset (points from point of grab to object center) - this.offset = Vec3.subtract(this.startPosition, this.pointOnPlane); // offset in world-space - MyAvatar.setJointTranslation(MOUSE_GRAB_JOINT, MyAvatar.worldToJointPoint(this.startPosition)); - MyAvatar.setJointRotation(MOUSE_GRAB_JOINT, MyAvatar.worldToJointRotation(this.lastRotation)); - - this.computeNewGrabPlane(); - this.moveEvent(event); - - var args = "mouse"; - Entities.callEntityMethod(this.entityID, "startDistanceGrab", args); - - Messages.sendLocalMessage('Hifi-Object-Manipulation', JSON.stringify({ - action: 'grab', - grabbedEntity: this.entityID - })); - - if (this.grabID) { - MyAvatar.releaseGrab(this.grabID); - this.grabID = null; - } - this.grabID = MyAvatar.grab(this.entityID, MOUSE_GRAB_JOINT, ZERO_VEC3, IDENTITY_QUAT); - - // TODO: play sounds again when we aren't leaking AudioInjector threads - //Audio.playSound(grabSound, { position: entityProperties.position, volume: VOLUME }); -}; - -Grabber.prototype.releaseEvent = function(event) { - if (event.button !== "LEFT" && !HMD.active) { - return; - } - - if (this.moveEventTimer) { - Script.clearTimeout(this.moveEventTimer); - this.moveEventTimer = null; - } - - if (this.isGrabbing) { - this.isGrabbing = false; - - Pointers.setRenderState(this.mouseRayEntities, ""); - Pointers.setLockEndUUID(this.mouseRayEntities, null, false); - - var args = "mouse"; - Entities.callEntityMethod(this.entityID, "releaseGrab", args); - - Messages.sendLocalMessage('Hifi-Object-Manipulation', JSON.stringify({ - action: 'release', - grabbedEntity: this.entityID, - joint: "mouse" - })); - - if (this.grabID) { - MyAvatar.releaseGrab(this.grabID); - this.grabID = null; - } - - MyAvatar.clearJointData(MOUSE_GRAB_JOINT); - - // TODO: play sounds again when we aren't leaking AudioInjector threads - //Audio.playSound(releaseSound, { position: entityProperties.position, volume: VOLUME }); - } -}; - -Grabber.prototype.scheduleMouseMoveProcessor = function(event) { - var _this = this; - if (!this.moveEventTimer) { - this.moveEventTimer = Script.setTimeout(function() { - _this.moveEventProcess(); - }, DELAY_FOR_30HZ); - } -}; - -Grabber.prototype.moveEvent = function(event) { - // during the handling of the event, do as little as possible. We save the updated mouse position, - // and start a timer to react to the change. If more changes arrive before the timer fires, only - // the last update will be considered. This is done to avoid backing-up Qt's event queue. - if (!this.isGrabbing || HMD.active) { - return; - } - mouse.updateDrag(event); - this.scheduleMouseMoveProcessor(); -}; - -Grabber.prototype.moveEventProcess = function() { - this.moveEventTimer = null; - var entityProperties = Entities.getEntityProperties(this.entityID, DISPATCHER_PROPERTIES); - if (!entityProperties || HMD.active) { - return; - } - - this.currentPosition = entityProperties.position; - - if (this.mode === "rotate") { - var drag = mouse.getDrag(); - var orientation = Camera.getOrientation(); - var dragOffset = Vec3.multiply(drag.x, Quat.getRight(orientation)); - dragOffset = Vec3.sum(dragOffset, Vec3.multiply(-drag.y, Quat.getUp(orientation))); - var axis = Vec3.cross(dragOffset, Quat.getForward(orientation)); - axis = Vec3.normalize(axis); - var ROTATE_STRENGTH = 0.4; // magic number tuned by hand - var angle = ROTATE_STRENGTH * Math.sqrt((drag.x * drag.x) + (drag.y * drag.y)); - var deltaQ = Quat.angleAxis(angle, axis); - - this.lastRotation = Quat.multiply(deltaQ, this.lastRotation); - MyAvatar.setJointRotation(MOUSE_GRAB_JOINT, MyAvatar.worldToJointRotation(this.lastRotation)); - - } else { - var newPointOnPlane; - - if (this.mode === "verticalCylinder") { - // for this mode we recompute the plane based on current Camera - var planeNormal = Quat.getForward(Camera.getOrientation()); - planeNormal.y = 0; - planeNormal = Vec3.normalize(planeNormal); - var pointOnCylinder = Vec3.multiply(planeNormal, this.xzDistanceToGrab); - pointOnCylinder = Vec3.sum(Camera.getPosition(), pointOnCylinder); - newPointOnPlane = mouseIntersectionWithPlane(pointOnCylinder, planeNormal, mouse.current, this.maxDistance); - } else { - var cameraPosition = Camera.getPosition(); - newPointOnPlane = mouseIntersectionWithPlane(this.pointOnPlane, this.planeNormal, mouse.current, this.maxDistance); - var relativePosition = Vec3.subtract(newPointOnPlane, cameraPosition); - var distance = Vec3.length(relativePosition); - if (distance > this.maxDistance) { - // clamp distance - relativePosition = Vec3.multiply(relativePosition, this.maxDistance / distance); - newPointOnPlane = Vec3.sum(relativePosition, cameraPosition); - } - } - - MyAvatar.setJointTranslation(MOUSE_GRAB_JOINT, MyAvatar.worldToJointPoint(Vec3.sum(newPointOnPlane, this.offset))); - } - - this.scheduleMouseMoveProcessor(); -}; - -Grabber.prototype.keyReleaseEvent = function(event) { - if (event.text === "SHIFT") { - this.liftKey = false; - } - if (event.text === "CONTROL") { - this.rotateKey = false; - } - this.computeNewGrabPlane(); -}; - -Grabber.prototype.keyPressEvent = function(event) { - if (event.text === "SHIFT") { - this.liftKey = true; - } - if (event.text === "CONTROL") { - this.rotateKey = true; - } - this.computeNewGrabPlane(); -}; - -Grabber.prototype.cleanup = function() { - Pointers.removePointer(this.mouseRayEntities); - Picks.removePick(this.mouseRayOverlays); - if (this.grabID) { - MyAvatar.releaseGrab(this.grabID); - this.grabID = null; - } -}; - -var grabber = new Grabber(); - -function pressEvent(event) { - grabber.pressEvent(event); -} - -function moveEvent(event) { - grabber.moveEvent(event); -} - -function releaseEvent(event) { - grabber.releaseEvent(event); -} - -function keyPressEvent(event) { - grabber.keyPressEvent(event); -} - -function keyReleaseEvent(event) { - grabber.keyReleaseEvent(event); -} - -function cleanup() { - grabber.cleanup(); -} - -Controller.mousePressEvent.connect(pressEvent); -Controller.mouseMoveEvent.connect(moveEvent); -Controller.mouseReleaseEvent.connect(releaseEvent); -Controller.keyPressEvent.connect(keyPressEvent); -Controller.keyReleaseEvent.connect(keyReleaseEvent); -Script.scriptEnding.connect(cleanup); - -}()); // END LOCAL_SCOPE diff --git a/scripts/simplifiedUI/system/controllers/handTouch.js b/scripts/simplifiedUI/system/controllers/handTouch.js deleted file mode 100644 index 5939c6e3d2..0000000000 --- a/scripts/simplifiedUI/system/controllers/handTouch.js +++ /dev/null @@ -1,959 +0,0 @@ -// -// scripts/system/libraries/handTouch.js -// -// Created by Luis Cuenca on 12/29/17 -// 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 -// - -/* jslint bitwise: true */ - -/* global Script, Overlays, Controller, Vec3, MyAvatar, Entities, RayPick -*/ - -(function () { - - var LEAP_MOTION_NAME = "LeapMotion"; - // Hand touch is disabled due to twitchy finger bug when walking near walls or tables. see BUGZ-154. - var handTouchEnabled = false; - var leapMotionEnabled = Controller.getRunningInputDeviceNames().indexOf(LEAP_MOTION_NAME) >= 0; - var MSECONDS_AFTER_LOAD = 2000; - var updateFingerWithIndex = 0; - var untouchableEntities = []; - - // Keys to access finger data - var fingerKeys = ["pinky", "ring", "middle", "index", "thumb"]; - - // Additionally close the hands to achieve a grabbing effect - var grabPercent = { left: 0, right: 0 }; - - var Palm = function() { - this.position = {x: 0, y: 0, z: 0}; - this.perpendicular = {x: 0, y: 0, z: 0}; - this.distance = 0; - this.fingers = { - pinky: {x: 0, y: 0, z: 0}, - middle: {x: 0, y: 0, z: 0}, - ring: {x: 0, y: 0, z: 0}, - thumb: {x: 0, y: 0, z: 0}, - index: {x: 0, y: 0, z: 0} - }; - this.set = false; - }; - - var palmData = { - left: new Palm(), - right: new Palm() - }; - - var handJointNames = {left: "LeftHand", right: "RightHand"}; - - // Store which fingers are touching - if all false restate the default poses - var isTouching = { - left: { - pinky: false, - middle: false, - ring: false, - thumb: false, - index: false - }, right: { - pinky: false, - middle: false, - ring: false, - thumb: false, - index: false - } - }; - - // frame count for transition to default pose - - var countToDefault = { - left: 0, - right: 0 - }; - - // joint data for open pose - var dataOpen = { - left: { - pinky: [ - {x: -0.0066, y: -0.0224, z: -0.2174, w: 0.9758}, - {x: 0.0112, y: 0.0001, z: 0.0093, w: 0.9999}, - {x: -0.0346, y: 0.0003, z: -0.0073, w: 0.9994} - ], - ring: [ - {x: -0.0029, y: -0.0094, z: -0.1413, w: 0.9899}, - {x: 0.0112, y: 0.0001, z: 0.0059, w: 0.9999}, - {x: -0.0346, y: 0.0002, z: -0.006, w: 0.9994} - ], - middle: [ - {x: -0.0016, y: 0, z: -0.0286, w: 0.9996}, - {x: 0.0112, y: -0.0001, z: -0.0063, w: 0.9999}, - {x: -0.0346, y: -0.0003, z: 0.0073, w: 0.9994} - ], - index: [ - {x: -0.0016, y: 0.0001, z: 0.0199, w: 0.9998}, - {x: 0.0112, y: 0, z: 0.0081, w: 0.9999}, - {x: -0.0346, y: 0.0008, z: -0.023, w: 0.9991} - ], - thumb: [ - {x: 0.0354, y: 0.0363, z: 0.3275, w: 0.9435}, - {x: -0.0945, y: 0.0938, z: 0.0995, w: 0.9861}, - {x: -0.0952, y: 0.0718, z: 0.1382, w: 0.9832} - ] - }, right: { - pinky: [ - {x: -0.0034, y: 0.023, z: 0.1051, w: 0.9942}, - {x: 0.0106, y: -0.0001, z: -0.0091, w: 0.9999}, - {x: -0.0346, y: -0.0003, z: 0.0075, w: 0.9994} - ], - ring: [ - {x: -0.0013, y: 0.0097, z: 0.0311, w: 0.9995}, - {x: 0.0106, y: -0.0001, z: -0.0056, w: 0.9999}, - {x: -0.0346, y: -0.0002, z: 0.0061, w: 0.9994} - ], - middle: [ - {x: -0.001, y: 0, z: 0.0285, w: 0.9996}, - {x: 0.0106, y: 0.0001, z: 0.0062, w: 0.9999}, - {x: -0.0346, y: 0.0003, z: -0.0074, w: 0.9994} - ], - index: [ - {x: -0.001, y: 0, z: -0.0199, w: 0.9998}, - {x: 0.0106, y: -0.0001, z: -0.0079, w: 0.9999}, - {x: -0.0346, y: -0.0008, z: 0.0229, w: 0.9991} - ], - thumb: [ - {x: 0.0355, y: -0.0363, z: -0.3263, w: 0.9439}, - {x: -0.0946, y: -0.0938, z: -0.0996, w: 0.9861}, - {x: -0.0952, y: -0.0719, z: -0.1376, w: 0.9833} - ] - } - }; - - // joint data for close pose - var dataClose = { - left: { - pinky: [ - {x: 0.5878, y: -0.1735, z: -0.1123, w: 0.7821}, - {x: 0.5704, y: 0.0053, z: 0.0076, w: 0.8213}, - {x: 0.6069, y: -0.0044, z: -0.0058, w: 0.7947} - ], - ring: [ - {x: 0.5761, y: -0.0989, z: -0.1025, w: 0.8048}, - {x: 0.5332, y: 0.0032, z: 0.005, w: 0.846}, - {x: 0.5773, y: -0.0035, z: -0.0049, w: 0.8165} - ], - middle: [ - {x: 0.543, y: -0.0469, z: -0.0333, w: 0.8378}, - {x: 0.5419, y: -0.0034, z: -0.0053, w: 0.8404}, - {x: 0.5015, y: 0.0037, z: 0.0063, w: 0.8651} - ], - index: [ - {x: 0.3051, y: -0.0156, z: -0.014, w: 0.9521}, - {x: 0.6414, y: 0.0051, z: 0.0063, w: 0.7671}, - {x: 0.5646, y: -0.013, z: -0.019, w: 0.8251} - ], - thumb: [ - {x: 0.313, y: -0.0348, z: 0.3192, w: 0.8938}, - {x: 0, y: 0, z: -0.37, w: 0.929}, - {x: 0, y: 0, z: -0.2604, w: 0.9655} - ] - }, right: { - pinky: [ - {x: 0.5881, y: 0.1728, z: 0.1114, w: 0.7823}, - {x: 0.5704, y: -0.0052, z: -0.0075, w: 0.8213}, - {x: 0.6069, y: 0.0046, z: 0.006, w: 0.7947} - ], - ring: [ - {x: 0.5729, y: 0.1181, z: 0.0898, w: 0.8061}, - {x: 0.5332, y: -0.003, z: -0.0048, w: 0.846}, - {x: 0.5773, y: 0.0035, z: 0.005, w: 0.8165} - ], - middle: [ - {x: 0.543, y: 0.0468, z: 0.0332, w: 0.8378}, - {x: 0.5419, y: 0.0034, z: 0.0052, w: 0.8404}, - {x: 0.5047, y: -0.0037, z: -0.0064, w: 0.8632} - ], - index: [ - {x: 0.306, y: -0.0076, z: -0.0584, w: 0.9502}, - {x: 0.6409, y: -0.005, z: -0.006, w: 0.7675}, - {x: 0.5646, y: 0.0129, z: 0.0189, w: 0.8251} - ], - thumb: [ - {x: 0.313, y: 0.0352, z: -0.3181, w: 0.8942}, - {x: 0, y: 0, z: 0.3698, w: 0.9291}, - {x: 0, y: 0, z: 0.2609, w: 0.9654} - ] - } - }; - - // snapshot for the default pose - var dataDefault = { - left: { - pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - index: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - set: false - }, - right: { - pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - index: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - set: false - } - }; - - // joint data for the current frame - var dataCurrent = { - left: { - pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - index: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}] - }, - right: { - pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - index: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}] - } - }; - - // interpolated values on joint data to smooth movement - var dataDelta = { - left: { - pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - index: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}] - }, - right: { - pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], - index: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}] - } - }; - - // Acquire an updated value per hand every 5 frames when finger is touching (faster in) - var touchAnimationSteps = 5; - - // Acquire an updated value per hand every 20 frames when finger is returning to default position (slower out) - var defaultAnimationSteps = 10; - - // Debugging info - var showSphere = false; - var showLines = false; - - // This get setup on creation - var linesCreated = false; - var sphereCreated = false; - - // Register object with API Debugger - var varsToDebug = { - scriptLoaded: false, - toggleDebugSphere: function() { - showSphere = !showSphere; - if (showSphere && !sphereCreated) { - createDebugSphere(); - sphereCreated = true; - } - }, - toggleDebugLines: function() { - showLines = !showLines; - if (showLines && !linesCreated) { - createDebugLines(); - linesCreated = true; - } - }, - fingerPercent: { - left: { - pinky: 0.38, - middle: 0.38, - ring: 0.38, - thumb: 0.38, - index: 0.38 - } , - right: { - pinky: 0.38, - middle: 0.38, - ring: 0.38, - thumb: 0.38, - index: 0.38 - } - }, - triggerValues: { - leftTriggerValue: 0, - leftTriggerClicked: 0, - rightTriggerValue: 0, - rightTriggerClicked: 0, - leftSecondaryValue: 0, - rightSecondaryValue: 0 - }, - palmData: { - left: new Palm(), - right: new Palm() - }, - offset: {x: 0, y: 0, z: 0}, - avatarLoaded: false - }; - - // Add/Subtract the joint data - per finger joint - function addVals(val1, val2, sign) { - var val = []; - if (val1.length !== val2.length) { - return; - } - for (var i = 0; i < val1.length; i++) { - val.push({x: 0, y: 0, z: 0, w: 0}); - val[i].x = val1[i].x + sign*val2[i].x; - val[i].y = val1[i].y + sign*val2[i].y; - val[i].z = val1[i].z + sign*val2[i].z; - val[i].w = val1[i].w + sign*val2[i].w; - } - return val; - } - - // Multiply/Divide the joint data - per finger joint - function multiplyValsBy(val1, num) { - var val = []; - for (var i = 0; i < val1.length; i++) { - val.push({x: 0, y: 0, z: 0, w: 0}); - val[i].x = val1[i].x * num; - val[i].y = val1[i].y * num; - val[i].z = val1[i].z * num; - val[i].w = val1[i].w * num; - } - return val; - } - - // Calculate the finger lengths by adding its joint lengths - function getJointDistances(jointNamesArray) { - var result = {distances: [], totalDistance: 0}; - for (var i = 1; i < jointNamesArray.length; i++) { - var index0 = MyAvatar.getJointIndex(jointNamesArray[i-1]); - var index1 = MyAvatar.getJointIndex(jointNamesArray[i]); - var pos0 = MyAvatar.getJointPosition(index0); - var pos1 = MyAvatar.getJointPosition(index1); - var distance = Vec3.distance(pos0, pos1); - result.distances.push(distance); - result.totalDistance += distance; - } - return result; - } - - function dataRelativeToWorld(side, dataIn, dataOut) { - var handJoint = handJointNames[side]; - var jointIndex = MyAvatar.getJointIndex(handJoint); - var worldPosHand = MyAvatar.jointToWorldPoint({x: 0, y: 0, z: 0}, jointIndex); - - dataOut.position = MyAvatar.jointToWorldPoint(dataIn.position, jointIndex); - var localPerpendicular = side === "right" ? {x: 0.2, y: 0, z: 1} : {x: -0.2, y: 0, z: 1}; - dataOut.perpendicular = Vec3.normalize( - Vec3.subtract(MyAvatar.jointToWorldPoint(localPerpendicular, jointIndex), worldPosHand) - ); - dataOut.distance = dataIn.distance; - for (var i = 0; i < fingerKeys.length; i++) { - var finger = fingerKeys[i]; - dataOut.fingers[finger] = MyAvatar.jointToWorldPoint(dataIn.fingers[finger], jointIndex); - } - } - - function dataRelativeToHandJoint(side, dataIn, dataOut) { - var handJoint = handJointNames[side]; - var jointIndex = MyAvatar.getJointIndex(handJoint); - var worldPosHand = MyAvatar.jointToWorldPoint({x: 0, y: 0, z: 0}, jointIndex); - - dataOut.position = MyAvatar.worldToJointPoint(dataIn.position, jointIndex); - dataOut.perpendicular = MyAvatar.worldToJointPoint(Vec3.sum(worldPosHand, dataIn.perpendicular), jointIndex); - dataOut.distance = dataIn.distance; - for (var i = 0; i < fingerKeys.length; i++) { - var finger = fingerKeys[i]; - dataOut.fingers[finger] = MyAvatar.worldToJointPoint(dataIn.fingers[finger], jointIndex); - } - } - - // Calculate touch field; Sphere at the center of the palm, - // perpendicular vector from the palm plane and origin of the the finger rays - function estimatePalmData(side) { - // Return data object - var data = new Palm(); - - var jointOffset = { x: 0, y: 0, z: 0 }; - - var upperSide = side[0].toUpperCase() + side.substring(1); - var jointIndexHand = MyAvatar.getJointIndex(upperSide + "Hand"); - - // Store position of the hand joint - var worldPosHand = MyAvatar.jointToWorldPoint(jointOffset, jointIndexHand); - var minusWorldPosHand = {x: -worldPosHand.x, y: -worldPosHand.y, z: -worldPosHand.z}; - - // Data for finger rays - var directions = {pinky: undefined, middle: undefined, ring: undefined, thumb: undefined, index: undefined}; - var positions = {pinky: undefined, middle: undefined, ring: undefined, thumb: undefined, index: undefined}; - - var thumbLength = 0; - var weightCount = 0; - - // Calculate palm center - var handJointWeight = 1; - var fingerJointWeight = 2; - - var palmCenter = {x: 0, y: 0, z: 0}; - palmCenter = Vec3.sum(worldPosHand, palmCenter); - - weightCount += handJointWeight; - - for (var i = 0; i < fingerKeys.length; i++) { - var finger = fingerKeys[i]; - var jointSuffixes = 4; // Get 4 joint names with suffix numbers (0, 1, 2, 3) - var jointNames = getJointNames(side, finger, jointSuffixes); - var fingerLength = getJointDistances(jointNames).totalDistance; - - var jointIndex = MyAvatar.getJointIndex(jointNames[0]); - positions[finger] = MyAvatar.jointToWorldPoint(jointOffset, jointIndex); - directions[finger] = Vec3.normalize(Vec3.sum(positions[finger], minusWorldPosHand)); - data.fingers[finger] = Vec3.sum(positions[finger], Vec3.multiply(fingerLength, directions[finger])); - if (finger !== "thumb") { - // finger joints have double the weight than the hand joint - // This would better position the palm estimation - - palmCenter = Vec3.sum(Vec3.multiply(fingerJointWeight, positions[finger]), palmCenter); - weightCount += fingerJointWeight; - } else { - thumbLength = fingerLength; - } - } - - // perpendicular change direction depending on the side - data.perpendicular = (side === "right") ? - Vec3.normalize(Vec3.cross(directions.index, directions.pinky)): - Vec3.normalize(Vec3.cross(directions.pinky, directions.index)); - - data.position = Vec3.multiply(1.0/weightCount, palmCenter); - - if (side === "right") { - varsToDebug.offset = MyAvatar.worldToJointPoint(worldPosHand, jointIndexHand); - } - - var palmDistanceMultiplier = 1.55; // 1.55 based on test/error for the sphere radius that best fits the hand - data.distance = palmDistanceMultiplier*Vec3.distance(data.position, positions.index); - - // move back thumb ray origin - var thumbBackMultiplier = 0.2; - data.fingers.thumb = Vec3.sum( - data.fingers.thumb, Vec3.multiply( -thumbBackMultiplier * thumbLength, data.perpendicular)); - - // return getDataRelativeToHandJoint(side, data); - dataRelativeToHandJoint(side, data, palmData[side]); - palmData[side].set = true; - } - - // Register GlobalDebugger for API Debugger - Script.registerValue("GlobalDebugger", varsToDebug); - - // store the rays for the fingers - only for debug purposes - var fingerRays = { - left: { - pinky: undefined, - middle: undefined, - ring: undefined, - thumb: undefined, - index: undefined - }, - right: { - pinky: undefined, - middle: undefined, - ring: undefined, - thumb: undefined, - index: undefined - } - }; - - // Create debug overlays - finger rays + palm rays + spheres - var palmRay, sphereHand; - - function createDebugLines() { - for (var i = 0; i < fingerKeys.length; i++) { - fingerRays.left[fingerKeys[i]] = Overlays.addOverlay("line3d", { - color: { red: 0, green: 0, blue: 255 }, - start: { x: 0, y: 0, z: 0 }, - end: { x: 0, y: 1, z: 0 }, - visible: showLines - }); - fingerRays.right[fingerKeys[i]] = Overlays.addOverlay("line3d", { - color: { red: 0, green: 0, blue: 255 }, - start: { x: 0, y: 0, z: 0 }, - end: { x: 0, y: 1, z: 0 }, - visible: showLines - }); - } - - palmRay = { - left: Overlays.addOverlay("line3d", { - color: { red: 255, green: 0, blue: 0 }, - start: { x: 0, y: 0, z: 0 }, - end: { x: 0, y: 1, z: 0 }, - visible: showLines - }), - right: Overlays.addOverlay("line3d", { - color: { red: 255, green: 0, blue: 0 }, - start: { x: 0, y: 0, z: 0 }, - end: { x: 0, y: 1, z: 0 }, - visible: showLines - }) - }; - linesCreated = true; - } - - function createDebugSphere() { - sphereHand = { - right: Overlays.addOverlay("sphere", { - position: MyAvatar.position, - color: { red: 0, green: 255, blue: 0 }, - scale: { x: 0.01, y: 0.01, z: 0.01 }, - visible: showSphere - }), - left: Overlays.addOverlay("sphere", { - position: MyAvatar.position, - color: { red: 0, green: 255, blue: 0 }, - scale: { x: 0.01, y: 0.01, z: 0.01 }, - visible: showSphere - }) - }; - sphereCreated = true; - } - - function acquireDefaultPose(side) { - for (var i = 0; i < fingerKeys.length; i++) { - var finger = fingerKeys[i]; - var jointSuffixes = 3; // We need rotation of the 0, 1 and 2 joints - var names = getJointNames(side, finger, jointSuffixes); - for (var j = 0; j < names.length; j++) { - var index = MyAvatar.getJointIndex(names[j]); - var rotation = MyAvatar.getJointRotation(index); - dataDefault[side][finger][j] = dataCurrent[side][finger][j] = rotation; - } - } - dataDefault[side].set = true; - } - - var rayPicks = { - left: { - pinky: undefined, - middle: undefined, - ring: undefined, - thumb: undefined, - index: undefined - }, - right: { - pinky: undefined, - middle: undefined, - ring: undefined, - thumb: undefined, - index: undefined - } - }; - - var dataFailed = { - left: { - pinky: 0, - middle: 0, - ring: 0, - thumb: 0, - index: 0 - }, - right: { - pinky: 0, - middle: 0, - ring: 0, - thumb: 0, - index: 0 - } - }; - - function clearRayPicks(side) { - for (var i = 0; i < fingerKeys.length; i++) { - var finger = fingerKeys[i]; - if (rayPicks[side][finger] !== undefined) { - RayPick.removeRayPick(rayPicks[side][finger]); - rayPicks[side][finger] = undefined; - } - } - } - - function createRayPicks(side) { - var data = palmData[side]; - clearRayPicks(side); - for (var i = 0; i < fingerKeys.length; i++) { - var finger = fingerKeys[i]; - var LOOKUP_DISTANCE_MULTIPLIER = 1.5; - var dist = LOOKUP_DISTANCE_MULTIPLIER*data.distance; - var checkOffset = { - x: data.perpendicular.x * dist, - y: data.perpendicular.y * dist, - z: data.perpendicular.z * dist - }; - - var checkPoint = Vec3.sum(data.position, Vec3.multiply(2, checkOffset)); - var sensorToWorldScale = MyAvatar.getSensorToWorldScale(); - - var origin = data.fingers[finger]; - - var direction = Vec3.normalize(Vec3.subtract(checkPoint, origin)); - - origin = Vec3.multiply(1/sensorToWorldScale, origin); - - rayPicks[side][finger] = RayPick.createRayPick( - { - "enabled": false, - "joint": handJointNames[side], - "posOffset": origin, - "dirOffset": direction, - "filter": RayPick.PICK_ENTITIES - } - ); - - RayPick.setPrecisionPicking(rayPicks[side][finger], true); - } - } - - function activateNextRay(side, index) { - var nextIndex = (index < fingerKeys.length-1) ? index + 1 : 0; - for (var i = 0; i < fingerKeys.length; i++) { - var finger = fingerKeys[i]; - if (i === nextIndex) { - RayPick.enableRayPick(rayPicks[side][finger]); - } else { - RayPick.disableRayPick(rayPicks[side][finger]); - } - } - } - - function updateSphereHand(side) { - var data = new Palm(); - dataRelativeToWorld(side, palmData[side], data); - varsToDebug.palmData[side] = palmData[side]; - - var palmPoint = data.position; - var LOOKUP_DISTANCE_MULTIPLIER = 1.5; - var dist = LOOKUP_DISTANCE_MULTIPLIER*data.distance; - - // Situate the debugging overlays - var checkOffset = { - x: data.perpendicular.x * dist, - y: data.perpendicular.y * dist, - z: data.perpendicular.z * dist - }; - - var spherePos = Vec3.sum(palmPoint, checkOffset); - var checkPoint = Vec3.sum(palmPoint, Vec3.multiply(2, checkOffset)); - - if (showLines) { - Overlays.editOverlay(palmRay[side], { - start: palmPoint, - end: checkPoint, - visible: showLines - }); - for (var i = 0; i < fingerKeys.length; i++) { - Overlays.editOverlay(fingerRays[side][fingerKeys[i]], { - start: data.fingers[fingerKeys[i]], - end: checkPoint, - visible: showLines - }); - } - } - - if (showSphere) { - Overlays.editOverlay(sphereHand[side], { - position: spherePos, - scale: { - x: 2*dist, - y: 2*dist, - z: 2*dist - }, - visible: showSphere - }); - } - - // Update the intersection of only one finger at a time - var finger = fingerKeys[updateFingerWithIndex]; - var nearbyEntities = Entities.findEntities(spherePos, dist); - // Filter the entities that are allowed to be touched - var touchableEntities = nearbyEntities.filter(function (id) { - return untouchableEntities.indexOf(id) == -1; - }); - var intersection; - if (rayPicks[side][finger] !== undefined) { - intersection = RayPick.getPrevRayPickResult(rayPicks[side][finger]); - } - - var animationSteps = defaultAnimationSteps; - var newFingerData = dataDefault[side][finger]; - var isAbleToGrab = false; - if (touchableEntities.length > 0) { - RayPick.setIncludeItems(rayPicks[side][finger], touchableEntities); - - if (intersection === undefined) { - return; - } - - var percent = 0; // Initialize - isAbleToGrab = intersection.intersects && intersection.distance < LOOKUP_DISTANCE_MULTIPLIER*dist; - if (isAbleToGrab && !getTouching(side)) { - acquireDefaultPose(side); // take a snapshot of the default pose before touch starts - newFingerData = dataDefault[side][finger]; // assign default pose to finger data - } - // Store if this finger is touching something - isTouching[side][finger] = isAbleToGrab; - if (isAbleToGrab) { - // update the open/close percentage for this finger - var FINGER_REACT_MULTIPLIER = 2.8; - - percent = intersection.distance/(FINGER_REACT_MULTIPLIER*dist); - - var THUMB_FACTOR = 0.2; - var FINGER_FACTOR = 0.05; - - // Amount of grab coefficient added to the fingers - thumb is higher - var grabMultiplier = finger === "thumb" ? THUMB_FACTOR : FINGER_FACTOR; - percent += grabMultiplier * grabPercent[side]; - - // Calculate new interpolation data - var totalDistance = addVals(dataClose[side][finger], dataOpen[side][finger], -1); - // Assign close/open ratio to finger to simulate touch - newFingerData = addVals(dataOpen[side][finger], multiplyValsBy(totalDistance, percent), 1); - animationSteps = touchAnimationSteps; - } - varsToDebug.fingerPercent[side][finger] = percent; - - } - if (!isAbleToGrab) { - dataFailed[side][finger] = dataFailed[side][finger] === 0 ? 1 : 2; - } else { - dataFailed[side][finger] = 0; - } - // If it only fails once it will not update increments - if (dataFailed[side][finger] !== 1) { - // Calculate animation increments - dataDelta[side][finger] = - multiplyValsBy(addVals(newFingerData, dataCurrent[side][finger], -1), 1.0/animationSteps); - } - } - - // Recreate the finger joint names - function getJointNames(side, finger, count) { - var names = []; - for (var i = 1; i < count+1; i++) { - var name = side[0].toUpperCase()+side.substring(1)+"Hand"+finger[0].toUpperCase()+finger.substring(1)+(i); - names.push(name); - } - return names; - } - - // Capture the controller values - var leftTriggerPress = function (value) { - varsToDebug.triggerValues.leftTriggerValue = value; - // the value for the trigger increments the hand-close percentage - grabPercent.left = value; - }; - - var leftTriggerClick = function (value) { - varsToDebug.triggerValues.leftTriggerClicked = value; - }; - - var rightTriggerPress = function (value) { - varsToDebug.triggerValues.rightTriggerValue = value; - // the value for the trigger increments the hand-close percentage - grabPercent.right = value; - }; - - var rightTriggerClick = function (value) { - varsToDebug.triggerValues.rightTriggerClicked = value; - }; - - var leftSecondaryPress = function (value) { - varsToDebug.triggerValues.leftSecondaryValue = value; - }; - - var rightSecondaryPress = function (value) { - varsToDebug.triggerValues.rightSecondaryValue = value; - }; - - var MAPPING_NAME = "com.highfidelity.handTouch"; - var mapping = Controller.newMapping(MAPPING_NAME); - mapping.from([Controller.Standard.RT]).peek().to(rightTriggerPress); - mapping.from([Controller.Standard.RTClick]).peek().to(rightTriggerClick); - mapping.from([Controller.Standard.LT]).peek().to(leftTriggerPress); - mapping.from([Controller.Standard.LTClick]).peek().to(leftTriggerClick); - - mapping.from([Controller.Standard.RB]).peek().to(rightSecondaryPress); - mapping.from([Controller.Standard.LB]).peek().to(leftSecondaryPress); - mapping.from([Controller.Standard.LeftGrip]).peek().to(leftSecondaryPress); - mapping.from([Controller.Standard.RightGrip]).peek().to(rightSecondaryPress); - - Controller.enableMapping(MAPPING_NAME); - - if (showLines && !linesCreated) { - createDebugLines(); - linesCreated = true; - } - - if (showSphere && !sphereCreated) { - createDebugSphere(); - sphereCreated = true; - } - - function getTouching(side) { - var animating = false; - for (var i = 0; i < fingerKeys.length; i++) { - var finger = fingerKeys[i]; - animating = animating || isTouching[side][finger]; - } - return animating; // return false only if none of the fingers are touching - } - - function reEstimatePalmData() { - ["right", "left"].forEach(function(side) { - estimatePalmData(side); - }); - } - - function recreateRayPicks() { - ["right", "left"].forEach(function(side) { - createRayPicks(side); - }); - } - - function cleanUp() { - ["right", "left"].forEach(function (side) { - if (linesCreated) { - Overlays.deleteOverlay(palmRay[side]); - } - if (sphereCreated) { - Overlays.deleteOverlay(sphereHand[side]); - } - clearRayPicks(side); - for (var i = 0; i < fingerKeys.length; i++) { - var finger = fingerKeys[i]; - var jointSuffixes = 3; // We need to clear the joints 0, 1 and 2 joints - var names = getJointNames(side, finger, jointSuffixes); - for (var j = 0; j < names.length; j++) { - var index = MyAvatar.getJointIndex(names[j]); - MyAvatar.clearJointData(index); - } - if (linesCreated) { - Overlays.deleteOverlay(fingerRays[side][finger]); - } - } - }); - } - - MyAvatar.shouldDisableHandTouchChanged.connect(function (shouldDisable) { - if (shouldDisable) { - if (handTouchEnabled) { - cleanUp(); - } - } else { - if (!handTouchEnabled) { - reEstimatePalmData(); - recreateRayPicks(); - } - } - handTouchEnabled = !shouldDisable; - }); - - Controller.inputDeviceRunningChanged.connect(function (deviceName, isEnabled) { - if (deviceName == LEAP_MOTION_NAME) { - leapMotionEnabled = isEnabled; - } - }); - - MyAvatar.disableHandTouchForIDChanged.connect(function (entityID, disable) { - var entityIndex = untouchableEntities.indexOf(entityID); - if (disable) { - if (entityIndex == -1) { - untouchableEntities.push(entityID); - } - } else { - if (entityIndex != -1) { - untouchableEntities.splice(entityIndex, 1); - } - } - }); - - MyAvatar.onLoadComplete.connect(function () { - // Sometimes the rig is not ready when this signal is trigger - console.log("avatar loaded"); - Script.setTimeout(function() { - reEstimatePalmData(); - recreateRayPicks(); - }, MSECONDS_AFTER_LOAD); - }); - - MyAvatar.sensorToWorldScaleChanged.connect(function() { - reEstimatePalmData(); - }); - - Script.scriptEnding.connect(function () { - cleanUp(); - }); - - Script.update.connect(function () { - - if (!handTouchEnabled || leapMotionEnabled) { - return; - } - - // index of the finger that needs to be updated this frame - updateFingerWithIndex = (updateFingerWithIndex < fingerKeys.length-1) ? updateFingerWithIndex + 1 : 0; - - ["right", "left"].forEach(function(side) { - - if (!palmData[side].set) { - reEstimatePalmData(); - recreateRayPicks(); - } - - // recalculate the base data - updateSphereHand(side); - activateNextRay(side, updateFingerWithIndex); - - // this vars manage the transition to default pose - var isHandTouching = getTouching(side); - countToDefault[side] = isHandTouching ? 0 : countToDefault[side] + 1; - - for (var i = 0; i < fingerKeys.length; i++) { - var finger = fingerKeys[i]; - var jointSuffixes = 3; // We need to update rotation of the 0, 1 and 2 joints - var names = getJointNames(side, finger, jointSuffixes); - - // Add the animation increments - dataCurrent[side][finger] = addVals(dataCurrent[side][finger], dataDelta[side][finger], 1); - - // update every finger joint - for (var j = 0; j < names.length; j++) { - var index = MyAvatar.getJointIndex(names[j]); - // if no finger is touching restate the default poses - if (isHandTouching || (dataDefault[side].set && - countToDefault[side] < fingerKeys.length*touchAnimationSteps)) { - var quatRot = dataCurrent[side][finger][j]; - MyAvatar.setJointRotation(index, quatRot); - } else { - MyAvatar.clearJointData(index); - } - } - } - }); - }); -}()); diff --git a/scripts/simplifiedUI/system/controllers/squeezeHands.js b/scripts/simplifiedUI/system/controllers/squeezeHands.js deleted file mode 100644 index 69f44f46a9..0000000000 --- a/scripts/simplifiedUI/system/controllers/squeezeHands.js +++ /dev/null @@ -1,184 +0,0 @@ -"use strict"; - -// -// controllers/squeezeHands.js -// -// Created by Anthony J. Thibault -// Copyright 2015 High Fidelity, Inc. -// -// Default script to drive the animation of the hands based on hand controllers. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// -/* global Script, MyAvatar, Messages, Controller */ -/* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ - -(function() { // BEGIN LOCAL_SCOPE - -var lastLeftTrigger = 0; -var lastRightTrigger = 0; -var leftHandOverlayAlpha = 0; -var rightHandOverlayAlpha = 0; - -// var CONTROLLER_DEAD_SPOT = 0.25; -var TRIGGER_SMOOTH_TIMESCALE = 0.1; -var OVERLAY_RAMP_RATE = 8.0; - -var animStateHandlerID; - -var leftIndexPointingOverride = 0; -var rightIndexPointingOverride = 0; -var leftThumbRaisedOverride = 0; -var rightThumbRaisedOverride = 0; - -var HIFI_POINT_INDEX_MESSAGE_CHANNEL = "Hifi-Point-Index"; - -var isLeftIndexPointing = false; -var isRightIndexPointing = false; -var isLeftThumbRaised = false; -var isRightThumbRaised = false; - -function clamp(val, min, max) { - return Math.min(Math.max(val, min), max); -} - -// function normalizeControllerValue(val) { -// return clamp((val - CONTROLLER_DEAD_SPOT) / (1 - CONTROLLER_DEAD_SPOT), 0, 1); -// } - -function lerp(a, b, alpha) { - return a * (1 - alpha) + b * alpha; -} - -function init() { - Script.update.connect(update); - animStateHandlerID = MyAvatar.addAnimationStateHandler( - animStateHandler, - [ - "leftHandOverlayAlpha", "leftHandGraspAlpha", - "rightHandOverlayAlpha", "rightHandGraspAlpha", - "isLeftHandGrasp", "isLeftIndexPoint", "isLeftThumbRaise", "isLeftIndexPointAndThumbRaise", - "isRightHandGrasp", "isRightIndexPoint", "isRightThumbRaise", "isRightIndexPointAndThumbRaise" - ] - ); - Messages.subscribe(HIFI_POINT_INDEX_MESSAGE_CHANNEL); - Messages.messageReceived.connect(handleMessages); -} - -function animStateHandler(props) { - return { - leftHandOverlayAlpha: leftHandOverlayAlpha, - leftHandGraspAlpha: lastLeftTrigger, - rightHandOverlayAlpha: rightHandOverlayAlpha, - rightHandGraspAlpha: lastRightTrigger, - - isLeftHandGrasp: !isLeftIndexPointing && !isLeftThumbRaised, - isLeftIndexPoint: isLeftIndexPointing && !isLeftThumbRaised, - isLeftThumbRaise: !isLeftIndexPointing && isLeftThumbRaised, - isLeftIndexPointAndThumbRaise: isLeftIndexPointing && isLeftThumbRaised, - - isRightHandGrasp: !isRightIndexPointing && !isRightThumbRaised, - isRightIndexPoint: isRightIndexPointing && !isRightThumbRaised, - isRightThumbRaise: !isRightIndexPointing && isRightThumbRaised, - isRightIndexPointAndThumbRaise: isRightIndexPointing && isRightThumbRaised - }; -} - -function update(dt) { - var leftTrigger = clamp(Controller.getValue(Controller.Standard.LT) + Controller.getValue(Controller.Standard.LeftGrip), 0, 1); - var rightTrigger = clamp(Controller.getValue(Controller.Standard.RT) + Controller.getValue(Controller.Standard.RightGrip), 0, 1); - - // Average last few trigger values together for a bit of smoothing - var tau = clamp(dt / TRIGGER_SMOOTH_TIMESCALE, 0, 1); - lastLeftTrigger = lerp(leftTrigger, lastLeftTrigger, tau); - lastRightTrigger = lerp(rightTrigger, lastRightTrigger, tau); - - // ramp on/off left hand overlay - var leftHandPose = Controller.getPoseValue(Controller.Standard.LeftHand); - if (leftHandPose.valid) { - leftHandOverlayAlpha = clamp(leftHandOverlayAlpha + OVERLAY_RAMP_RATE * dt, 0, 1); - } else { - leftHandOverlayAlpha = clamp(leftHandOverlayAlpha - OVERLAY_RAMP_RATE * dt, 0, 1); - } - - // ramp on/off right hand overlay - var rightHandPose = Controller.getPoseValue(Controller.Standard.RightHand); - if (rightHandPose.valid) { - rightHandOverlayAlpha = clamp(rightHandOverlayAlpha + OVERLAY_RAMP_RATE * dt, 0, 1); - } else { - rightHandOverlayAlpha = clamp(rightHandOverlayAlpha - OVERLAY_RAMP_RATE * dt, 0, 1); - } - - // Pointing index fingers and raising thumbs - isLeftIndexPointing = (leftIndexPointingOverride > 0) || (leftHandPose.valid && Controller.getValue(Controller.Standard.LeftIndexPoint) === 1); - isRightIndexPointing = (rightIndexPointingOverride > 0) || (rightHandPose.valid && Controller.getValue(Controller.Standard.RightIndexPoint) === 1); - isLeftThumbRaised = (leftThumbRaisedOverride > 0) || (leftHandPose.valid && Controller.getValue(Controller.Standard.LeftThumbUp) === 1); - isRightThumbRaised = (rightThumbRaisedOverride > 0) || (rightHandPose.valid && Controller.getValue(Controller.Standard.RightThumbUp) === 1); -} - -function handleMessages(channel, message, sender) { - if (sender === MyAvatar.sessionUUID && channel === HIFI_POINT_INDEX_MESSAGE_CHANNEL) { - var data = JSON.parse(message); - - if (data.pointIndex !== undefined) { - if (data.pointIndex) { - leftIndexPointingOverride++; - rightIndexPointingOverride++; - } else { - leftIndexPointingOverride--; - rightIndexPointingOverride--; - } - } - if (data.pointLeftIndex !== undefined) { - if (data.pointLeftIndex) { - leftIndexPointingOverride++; - } else { - leftIndexPointingOverride--; - } - } - if (data.pointRightIndex !== undefined) { - if (data.pointRightIndex) { - rightIndexPointingOverride++; - } else { - rightIndexPointingOverride--; - } - } - if (data.raiseThumbs !== undefined) { - if (data.raiseThumbs) { - leftThumbRaisedOverride++; - rightThumbRaisedOverride++; - } else { - leftThumbRaisedOverride--; - rightThumbRaisedOverride--; - } - } - if (data.raiseLeftThumb !== undefined) { - if (data.raiseLeftThumb) { - leftThumbRaisedOverride++; - } else { - leftThumbRaisedOverride--; - } - } - if (data.raiseRightThumb !== undefined) { - if (data.raiseRightThumb) { - rightThumbRaisedOverride++; - } else { - rightThumbRaisedOverride--; - } - } - } -} - -function shutdown() { - Script.update.disconnect(update); - MyAvatar.removeAnimationStateHandler(animStateHandlerID); - Messages.unsubscribe(HIFI_POINT_INDEX_MESSAGE_CHANNEL); - Messages.messageReceived.disconnect(handleMessages); -} - -Script.scriptEnding.connect(shutdown); - -init(); - -}()); // END LOCAL_SCOPE diff --git a/scripts/simplifiedUI/system/controllers/toggleAdvancedMovementForHandControllers.js b/scripts/simplifiedUI/system/controllers/toggleAdvancedMovementForHandControllers.js deleted file mode 100644 index 92f72f8724..0000000000 --- a/scripts/simplifiedUI/system/controllers/toggleAdvancedMovementForHandControllers.js +++ /dev/null @@ -1,174 +0,0 @@ -"use strict"; - -// Created by james b. pollack @imgntn on 8/18/2016 -// Copyright 2016 High Fidelity, Inc. -// -// advanced movements settings are in individual controller json files -// what we do is check the status of the 'advance movement' checkbox when you enter HMD mode -// if 'advanced movement' is checked...we give you the defaults that are in the json. -// if 'advanced movement' is not checked... we override the advanced controls with basic ones. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - -/* jslint bitwise: true */ - -/* global Script, Quat, MyAvatar, HMD, Controller, Messages*/ - -(function() { // BEGIN LOCAL_SCOPE - - var TWO_SECONDS_INTERVAL = 2000; - var FLYING_MAPPING_NAME = 'Hifi-Flying-Dev-' + Math.random(); - var DRIVING_MAPPING_NAME = 'Hifi-Driving-Dev-' + Math.random(); - - var flyingMapping = null; - var drivingMapping = null; - - var TURN_RATE = 1000; - var isDisabled = false; - - var previousFlyingState = MyAvatar.getFlyingEnabled(); - var previousDrivingState = false; - - function rotate180() { - var newOrientation = Quat.multiply(MyAvatar.orientation, Quat.angleAxis(180, { - x: 0, - y: 1, - z: 0 - })); - MyAvatar.orientation = newOrientation; - } - - var inFlipTurn = false; - - function registerBasicMapping() { - - drivingMapping = Controller.newMapping(DRIVING_MAPPING_NAME); - drivingMapping.from(Controller.Standard.LY).to(function(value) { - if (isDisabled) { - return; - } - - if (value === 1 && Controller.Hardware.OculusTouch !== undefined) { - rotate180(); - } else if (Controller.Hardware.Vive !== undefined) { - if (value > 0.75 && inFlipTurn === false) { - inFlipTurn = true; - rotate180(); - Script.setTimeout(function() { - inFlipTurn = false; - }, TURN_RATE); - } - } - return; - }); - - flyingMapping = Controller.newMapping(FLYING_MAPPING_NAME); - flyingMapping.from(Controller.Standard.RY).to(function(value) { - if (isDisabled) { - return; - } - - if (value === 1 && Controller.Hardware.OculusTouch !== undefined) { - rotate180(); - } else if (Controller.Hardware.Vive !== undefined) { - if (value > 0.75 && inFlipTurn === false) { - inFlipTurn = true; - rotate180(); - Script.setTimeout(function() { - inFlipTurn = false; - }, TURN_RATE); - } - } - return; - }); - } - - function scriptEnding() { - Controller.disableMapping(FLYING_MAPPING_NAME); - Controller.disableMapping(DRIVING_MAPPING_NAME); - } - - Script.scriptEnding.connect(scriptEnding); - - registerBasicMapping(); - - Script.setTimeout(function() { - if (MyAvatar.useAdvanceMovementControls) { - Controller.disableMapping(DRIVING_MAPPING_NAME); - } else { - Controller.enableMapping(DRIVING_MAPPING_NAME); - } - - if (MyAvatar.getFlyingEnabled()) { - Controller.disableMapping(FLYING_MAPPING_NAME); - } else { - Controller.enableMapping(FLYING_MAPPING_NAME); - } - }, 100); - - - HMD.displayModeChanged.connect(function(isHMDMode) { - if (isHMDMode) { - if (Controller.Hardware.Vive !== undefined || Controller.Hardware.OculusTouch !== undefined) { - if (MyAvatar.useAdvancedMovementControls) { - Controller.disableMapping(DRIVING_MAPPING_NAME); - } else { - Controller.enableMapping(DRIVING_MAPPING_NAME); - } - - if (MyAvatar.getFlyingEnabled()) { - Controller.disableMapping(FLYING_MAPPING_NAME); - } else { - Controller.enableMapping(FLYING_MAPPING_NAME); - } - - } - } - }); - - - function update() { - if ((Controller.Hardware.Vive !== undefined || Controller.Hardware.OculusTouch !== undefined) && HMD.active) { - var flying = MyAvatar.getFlyingEnabled(); - var driving = MyAvatar.useAdvancedMovementControls; - - if (flying !== previousFlyingState) { - if (flying) { - Controller.disableMapping(FLYING_MAPPING_NAME); - } else { - Controller.enableMapping(FLYING_MAPPING_NAME); - } - - previousFlyingState = flying; - } - - if (driving !== previousDrivingState) { - if (driving) { - Controller.disableMapping(DRIVING_MAPPING_NAME); - } else { - Controller.enableMapping(DRIVING_MAPPING_NAME); - } - previousDrivingState = driving; - } - } - Script.setTimeout(update, TWO_SECONDS_INTERVAL); - } - - Script.setTimeout(update, TWO_SECONDS_INTERVAL); - - var HIFI_ADVANCED_MOVEMENT_DISABLER_CHANNEL = 'Hifi-Advanced-Movement-Disabler'; - function handleMessage(channel, message, sender) { - if (channel === HIFI_ADVANCED_MOVEMENT_DISABLER_CHANNEL) { - if (message === 'disable') { - isDisabled = true; - } else if (message === 'enable') { - isDisabled = false; - } - } - } - - Messages.subscribe(HIFI_ADVANCED_MOVEMENT_DISABLER_CHANNEL); - Messages.messageReceived.connect(handleMessage); - -}()); // END LOCAL_SCOPE diff --git a/scripts/simplifiedUI/system/controllers/touchControllerConfiguration.js b/scripts/simplifiedUI/system/controllers/touchControllerConfiguration.js deleted file mode 100644 index 991b77b8af..0000000000 --- a/scripts/simplifiedUI/system/controllers/touchControllerConfiguration.js +++ /dev/null @@ -1,372 +0,0 @@ - -// -// touchControllerConfiguration.js -// -// Created by Ryan Huffman on 12/06/16 -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -/* globals TOUCH_CONTROLLER_CONFIGURATION_LEFT:true, TOUCH_CONTROLLER_CONFIGURATION_RIGHT:true, - Quat, Vec3, Script, MyAvatar, Controller */ -/* eslint camelcase: ["error", { "properties": "never" }] */ - -var leftBaseRotation = Quat.multiply( - Quat.fromPitchYawRollDegrees(-90, 0, 0), - Quat.fromPitchYawRollDegrees(0, 0, 90) -); -var rightBaseRotation = Quat.multiply( - Quat.fromPitchYawRollDegrees(-90, 0, 0), - Quat.fromPitchYawRollDegrees(0, 0, -90) -); - -// keep these in sync with the values from OculusHelpers.cpp -var CONTROLLER_LENGTH_OFFSET = 0.0762; -// var CONTROLLER_LATERAL_OFFSET = 0.0381; -// var CONTROLLER_VERTICAL_OFFSET = 0.0381; -// var CONTROLLER_FORWARD_OFFSET = 0.1524; - -var leftBasePosition = Vec3.multiplyQbyV(leftBaseRotation, { - x: -CONTROLLER_LENGTH_OFFSET / 2.0, - y: CONTROLLER_LENGTH_OFFSET / 2.0, - z: CONTROLLER_LENGTH_OFFSET * 1.5 -}); -var rightBasePosition = Vec3.multiplyQbyV(rightBaseRotation, { - x: CONTROLLER_LENGTH_OFFSET / 2.0, - y: CONTROLLER_LENGTH_OFFSET / 2.0, - z: CONTROLLER_LENGTH_OFFSET * 1.5 -}); - -var BASE_URL = Script.resourcesPath() + "meshes/controller/touch/"; - -TOUCH_CONTROLLER_CONFIGURATION_LEFT = { - name: "Touch", - controllers: [ - { - modelURL: BASE_URL + "touch_l_body.fbx", - jointIndex: MyAvatar.getJointIndex("_CAMERA_RELATIVE_CONTROLLER_LEFTHAND"), - naturalPosition: { x: 0.01648625358939171, y: -0.03551870584487915, z: -0.018527675420045853 }, - dimensions: { x: 0.11053799837827682, y: 0.0995776429772377, z: 0.10139888525009155 }, - rotation: leftBaseRotation, - position: leftBasePosition, - - parts: { - tips: { - type: "static", - modelURL: BASE_URL + "Oculus-Labels-L.fbx", - naturalPosition: { x: -0.022335469722747803, y: 0.00022516027092933655, z: 0.020340695977211 }, - naturalDimensions: { x: 0.132063, y: 0.0856, z: 0.130282 }, - - textureName: "blank", - defaultTextureLayer: "blank", - textureLayers: { - blank: { - defaultTextureURL: BASE_URL + "Oculus-Labels-L.fbx/Oculus-Labels-L.fbm/Blank.png" - }, - trigger: { - defaultTextureURL: BASE_URL + "Oculus-Labels-L.fbx/Oculus-Labels-L.fbm/Trigger.png" - }, - arrows: { - defaultTextureURL: BASE_URL + "Oculus-Labels-L.fbx/Oculus-Labels-L.fbm/Rotate.png" - }, - grip: { - defaultTextureURL: BASE_URL + "Oculus-Labels-L.fbx/Oculus-Labels-L.fbm/Grip-oculus.png" - }, - teleport: { - defaultTextureURL: BASE_URL + "Oculus-Labels-L.fbx/Oculus-Labels-L.fbm/Teleport.png" - }, - both_triggers: { - defaultTextureURL: BASE_URL + "Oculus-Labels-L.fbx/Oculus-Labels-L.fbm/Grip-Trigger.png" - }, - } - }, - - trigger: { - type: "rotational", - modelURL: BASE_URL + "touch_l_trigger.fbx", - naturalPosition: { x: 0.0008544912561774254, y: -0.019867943599820137, z: 0.018800459802150726 }, - naturalDimensions: { x: 0.027509, y: 0.025211, z: 0.018443 }, - - // rotational - input: Controller.Standard.LT, - origin: { x: 0, y: -0.015, z: -0.00 }, - minValue: 0.0, - maxValue: 1.0, - axis: { x: 1, y: 0, z: 0 }, - maxAngle: 17, - - textureName: "tex-highlight", - defaultTextureLayer: "normal", - textureLayers: { - normal: { - defaultTextureURL: BASE_URL + "touch_l_trigger.fbx/touch_l_trigger.fbm/L_controller_DIF.jpg", - }, - highlight: { - defaultTextureURL: BASE_URL + "touch_l_trigger.fbx/touch_l_trigger.fbm/L_controller-highlight_DIF.jpg", - } - } - }, - - grip: { - type: "linear", - modelURL: BASE_URL + "touch_l_bumper.fbx", - naturalPosition: { x: 0.00008066371083259583, y: -0.02715788595378399, z: -0.02448512241244316 }, - naturalDimensions: { x: 0.017444, y: 0.020297, z: 0.026003 }, - - // linear properties - // Offset from origin = 0.36470, 0.11048, 0.11066 - input: "OculusTouch.LeftGrip", - axis: { x: 1, y: 0.302933918, z: 0.302933918 }, - maxTranslation: 0.003967, - - textureName: "tex-highlight", - defaultTextureLayer: "normal", - textureLayers: { - normal: { - defaultTextureURL: BASE_URL + "touch_l_bumper.fbx/touch_l_bumper.fbm/L_controller_DIF.jpg", - }, - highlight: { - defaultTextureURL: BASE_URL + "touch_l_bumper.fbx/touch_l_bumper.fbm/L_controller-highlight_DIF.jpg", - } - } - }, - - joystick: { - type: "joystick", - modelURL: BASE_URL + "touch_l_joystick.fbx", - naturalPosition: { x: 0.0075613949447870255, y: -0.008225866593420506, z: 0.004792703315615654 }, - naturalDimensions: { x: 0.027386, y: 0.033254, z: 0.027272 }, - - // joystick - xInput: "OculusTouch.LX", - yInput: "OculusTouch.LY", - originOffset: { x: 0, y: -0.0028564, z: -0.00 }, - xHalfAngle: 20, - yHalfAngle: 20, - - textureName: "tex-highlight", - defaultTextureLayer: "normal", - textureLayers: { - normal: { - defaultTextureURL: BASE_URL + "touch_l_joystick.fbx/touch_l_joystick.fbm/L_controller_DIF.jpg", - }, - highlight: { - defaultTextureURL: BASE_URL + "touch_l_joystick.fbx/touch_l_joystick.fbm/L_controller-highlight_DIF.jpg", - } - } - }, - - button_a: { - type: "linear", - modelURL: BASE_URL + "touch_l_button_x.fbx", - naturalPosition: { x: -0.009307309985160828, y: -0.00005015172064304352, z: -0.012594521045684814 }, - naturalDimensions: { x: 0.009861, y: 0.004345, z: 0.00982 }, - - input: "OculusTouch.X", - axis: { x: 0, y: -1, z: 0 }, - maxTranslation: 0.001, - - textureName: "tex-highlight", - defaultTextureLayer: "normal", - textureLayers: { - normal: { - defaultTextureURL: BASE_URL + "touch_l_button_x.fbx/touch_l_button_x.fbm/L_controller_DIF.jpg", - }, - highlight: { - defaultTextureURL: BASE_URL + "touch_l_button_x.fbx/touch_l_button_x.fbm/L_controller-highlight_DIF.jpg", - } - } - }, - - button_b: { - type: "linear", - modelURL: BASE_URL + "touch_l_button_y.fbx", - naturalPosition: { x: -0.01616849936544895, y: -0.000050364527851343155, z: 0.0017703399062156677 }, - naturalDimensions: { x: 0.010014, y: 0.004412, z: 0.009972 }, - - input: "OculusTouch.Y", - axis: { x: 0, y: -1, z: 0 }, - maxTranslation: 0.001, - - textureName: "tex-highlight", - defaultTextureLayer: "normal", - textureLayers: { - normal: { - defaultTextureURL: BASE_URL + "touch_l_button_y.fbx/touch_l_button_y.fbm/L_controller_DIF.jpg", - }, - highlight: { - defaultTextureURL: BASE_URL + "touch_l_button_y.fbx/touch_l_button_y.fbm/L_controller-highlight_DIF.jpg", - } - } - }, - } - } - ] -}; - -TOUCH_CONTROLLER_CONFIGURATION_RIGHT = { - name: "Touch", - controllers: [ - { - modelURL: BASE_URL + "touch_r_body.fbx", - jointIndex: MyAvatar.getJointIndex("_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND"), - naturalPosition: { x: -0.016486231237649918, y: -0.03551865369081497, z: -0.018527653068304062 }, - dimensions: { x: 0.11053784191608429, y: 0.09957750141620636, z: 0.10139875113964081 }, - rotation: rightBaseRotation, - position: rightBasePosition, - - parts: { - tips: { - type: "static", - modelURL: BASE_URL + "Oculus-Labels-R.fbx", - naturalPosition: { x: 0.009739525616168976, y: -0.0017818436026573181, z: 0.016794726252555847 }, - naturalDimensions: { x: 0.129049, y: 0.078297, z: 0.139492 }, - - textureName: "blank", - defaultTextureLayer: "blank", - textureLayers: { - blank: { - defaultTextureURL: BASE_URL + "Oculus-Labels-R.fbx/Oculus-Labels-R.fbm/Blank.png" - }, - trigger: { - defaultTextureURL: BASE_URL + "Oculus-Labels-R.fbx/Oculus-Labels-R.fbm/Trigger.png" - }, - arrows: { - defaultTextureURL: BASE_URL + "Oculus-Labels-R.fbx/Oculus-Labels-R.fbm/Rotate.png" - }, - grip: { - defaultTextureURL: BASE_URL + "Oculus-Labels-R.fbx/Oculus-Labels-R.fbm/Grip-oculus.png" - }, - teleport: { - defaultTextureURL: BASE_URL + "Oculus-Labels-R.fbx/Oculus-Labels-R.fbm/Teleport.png" - }, - both_triggers: { - defaultTextureURL: BASE_URL + "Oculus-Labels-R.fbx/Oculus-Labels-R.fbm/Grip-Trigger.png" - }, - } - }, - - trigger: { - type: "rotational", - modelURL: BASE_URL + "touch_r_trigger.fbx", - naturalPosition: { x: -0.0008544912561774254, y: -0.019867943599820137, z: 0.018800459802150726 }, - naturalDimensions: { x: 0.027384, y: 0.025201, z: 0.018425 }, - - // rotational - input: "OculusTouch.RT", - origin: { x: 0, y: -0.015, z: 0 }, - minValue: 0.0, - maxValue: 1.0, - axis: { x: 1, y: 0, z: 0 }, - maxAngle: 17, - - textureName: "tex-highlight", - defaultTextureLayer: "normal", - textureLayers: { - normal: { - defaultTextureURL: BASE_URL + "touch_r_trigger.fbx/touch_r_trigger.fbm/R_controller_DIF.jpg", - }, - highlight: { - defaultTextureURL: BASE_URL + "touch_r_trigger.fbx/touch_r_trigger.fbm/R_controller-highlight_DIF.jpg", - } - } - }, - - grip: { - type: "linear", - modelURL: BASE_URL + "touch_r_bumper.fbx", - naturalPosition: { x: -0.0000806618481874466, y: -0.027157839387655258, z: -0.024485092610120773 }, - naturalDimensions: { x: 0.017268, y: 0.020366, z: 0.02599 }, - - // linear properties - // Offset from origin = 0.36470, 0.11048, 0.11066 - input: "OculusTouch.RightGrip", - axis: { x: -1, y: 0.302933918, z: 0.302933918 }, - maxTranslation: 0.003967, - - - textureName: "tex-highlight", - defaultTextureLayer: "normal", - textureLayers: { - normal: { - defaultTextureURL: BASE_URL + "touch_r_bumper.fbx/touch_r_bumper.fbm/R_controller_DIF.jpg", - }, - highlight: { - defaultTextureURL: BASE_URL + "touch_r_bumper.fbx/touch_r_bumper.fbm/R_controller-highlight_DIF.jpg", - } - } - }, - - joystick: { - type: "joystick", - modelURL: BASE_URL + "touch_r_joystick.fbx", - naturalPosition: { x: -0.007561382371932268, y: -0.008225853554904461, z: 0.00479268841445446 }, - naturalDimensions: { x: 0.027272, y: 0.033254, z: 0.027272 }, - - // joystick - xInput: "OculusTouch.RX", - yInput: "OculusTouch.RY", - originOffset: { x: 0, y: -0.0028564, z: 0 }, - xHalfAngle: 20, - yHalfAngle: 20, - - textureName: "tex-highlight", - defaultTextureLayer: "normal", - textureLayers: { - normal: { - defaultTextureURL: BASE_URL + "touch_r_joystick.fbx/touch_r_joystick.fbm/R_controller_DIF.jpg", - }, - highlight: { - defaultTextureURL: BASE_URL + "touch_r_joystick.fbx/touch_r_joystick.fbm/R_controller-highlight_DIF.jpg", - } - } - }, - - button_a: { - type: "linear", - modelURL: BASE_URL + "touch_r_button_a.fbx", - naturalPosition: { x: 0.009307296946644783, y: -0.00005015172064304352, z: -0.012594504281878471 }, - naturalDimensions: { x: 0.00982, y: 0.004345, z: 0.00982 }, - - input: "OculusTouch.A", - axis: { x: 0, y: -1, z: 0 }, - maxTranslation: 0.001, - - textureName: "tex-highlight", - defaultTextureLayer: "normal", - textureLayers: { - normal: { - defaultTextureURL: BASE_URL + "touch_r_button_a.fbx/touch_r_button_a.fbm/R_controller_DIF.jpg", - }, - highlight: { - defaultTextureURL: BASE_URL + "touch_r_button_a.fbx/touch_r_button_a.fbm/R_controller-highlight_DIF.jpg", - } - } - }, - - button_b: { - type: "linear", - modelURL: BASE_URL + "touch_r_button_b.fbx", - naturalPosition: { x: 0.01616847701370716, y: -0.000050364527851343155, z: 0.0017703361809253693 }, - naturalDimensions: { x: 0.009972, y: 0.004412, z: 0.009972 }, - - input: "OculusTouch.B", - axis: { x: 0, y: -1, z: 0 }, - maxTranslation: 0.001, - - textureName: "tex-highlight", - defaultTextureLayer: "normal", - textureLayers: { - normal: { - defaultTextureURL: BASE_URL + "touch_r_button_b.fbx/touch_r_button_b.fbm/R_controller_DIF.jpg", - }, - highlight: { - defaultTextureURL: BASE_URL + "touch_r_button_b.fbx/touch_r_button_b.fbm/R_controller-highlight_DIF.jpg", - } - } - }, - } - } - ] -}; diff --git a/scripts/simplifiedUI/system/controllers/viveControllerConfiguration.js b/scripts/simplifiedUI/system/controllers/viveControllerConfiguration.js deleted file mode 100644 index 09fd8adacc..0000000000 --- a/scripts/simplifiedUI/system/controllers/viveControllerConfiguration.js +++ /dev/null @@ -1,343 +0,0 @@ -// -// viveControllerConfiguration.js -// -// Created by Anthony J. Thibault on 10/20/16 -// Originally created by Ryan Huffman on 9/21/2016 -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -/* globals VIVE_CONTROLLER_CONFIGURATION_LEFT:true, VIVE_CONTROLLER_CONFIGURATION_RIGHT:true, - MyAvatar, Quat, Script, Vec3, Controller */ -/* eslint camelcase: ["error", { "properties": "never" }] */ - -// var LEFT_JOINT_INDEX = MyAvatar.getJointIndex("_CONTROLLER_LEFTHAND"); -// var RIGHT_JOINT_INDEX = MyAvatar.getJointIndex("_CONTROLLER_RIGHTHAND"); - -var leftBaseRotation = Quat.multiply( - Quat.fromPitchYawRollDegrees(0, 0, 45), - Quat.multiply( - Quat.fromPitchYawRollDegrees(90, 0, 0), - Quat.fromPitchYawRollDegrees(0, 0, 90) - ) -); - -var rightBaseRotation = Quat.multiply( - Quat.fromPitchYawRollDegrees(0, 0, -45), - Quat.multiply( - Quat.fromPitchYawRollDegrees(90, 0, 0), - Quat.fromPitchYawRollDegrees(0, 0, -90) - ) -); - -// keep these in sync with the values from plugins/openvr/src/OpenVrHelpers.cpp:303 -var CONTROLLER_LATERAL_OFFSET = 0.0381; -var CONTROLLER_VERTICAL_OFFSET = 0.0495; -var CONTROLLER_FORWARD_OFFSET = 0.1371; -var leftBasePosition = { - x: CONTROLLER_VERTICAL_OFFSET, - y: CONTROLLER_FORWARD_OFFSET, - z: CONTROLLER_LATERAL_OFFSET -}; -var rightBasePosition = { - x: -CONTROLLER_VERTICAL_OFFSET, - y: CONTROLLER_FORWARD_OFFSET, - z: CONTROLLER_LATERAL_OFFSET -}; - -var viveNaturalDimensions = { - x: 0.1174320001155138, - y: 0.08361100335605443, - z: 0.21942697931081057 -}; - -var viveNaturalPosition = { - x: 0, - y: -0.034076502197422087, - z: 0.06380049744620919 -}; - -var BASE_URL = Script.resourcesPath(); -// var TIP_TEXTURE_BASE_URL = BASE_URL + "meshes/controller/vive_tips.fbm/"; - -var viveModelURL = BASE_URL + "meshes/controller/vive_body.fbx"; -// var viveTipsModelURL = BASE_URL + "meshes/controller/vive_tips.fbx"; -var viveTriggerModelURL = "meshes/controller/vive_trigger.fbx"; - -VIVE_CONTROLLER_CONFIGURATION_LEFT = { - name: "Vive", - controllers: [ - { - modelURL: viveModelURL, - jointIndex: MyAvatar.getJointIndex("_CAMERA_RELATIVE_CONTROLLER_LEFTHAND"), - naturalPosition: viveNaturalPosition, - rotation: leftBaseRotation, - position: Vec3.multiplyQbyV(Quat.fromPitchYawRollDegrees(0, 0, 45), leftBasePosition), - - dimensions: viveNaturalDimensions, - - parts: { - // DISABLED FOR NOW - /* - tips: { - type: "static", - modelURL: viveTipsModelURL, - naturalPosition: {"x":-0.004377640783786774,"y":-0.034371938556432724,"z":0.06769277155399323}, - naturalDimensions: {x: 0.191437, y: 0.094095, z: 0.085656}, - - textureName: "Tex.Blank", - defaultTextureLayer: "blank", - textureLayers: { - blank: { - defaultTextureURL: TIP_TEXTURE_BASE_URL + "/Blank.png" - }, - trigger: { - defaultTextureURL: TIP_TEXTURE_BASE_URL + "/Trigger.png" - }, - arrows: { - defaultTextureURL: TIP_TEXTURE_BASE_URL + "/Rotate.png" - }, - grip: { - defaultTextureURL: TIP_TEXTURE_BASE_URL + "/Grip.png" - }, - teleport: { - defaultTextureURL: TIP_TEXTURE_BASE_URL + "/Teleport.png" - } - } - }, - */ - - // The touchpad type draws a dot indicating the current touch/thumb position - // and swaps in textures based on the thumb position. - touchpad: { - type: "touchpad", - modelURL: BASE_URL + "meshes/controller/vive_trackpad.fbx", - visibleInput: "Vive.RSTouch", - xInput: "Vive.LX", - yInput: "Vive.LY", - naturalPosition: {"x":0,"y":0.000979491975158453,"z":0.04872849956154823}, - naturalDimensions: {x: 0.042824, y: 0.012537, z: 0.043115}, - minValue: 0.0, - maxValue: 1.0, - minPosition: { x: -0.035, y: 0.004, z: -0.005 }, - maxPosition: { x: -0.035, y: 0.004, z: -0.005 }, - disable_textureName: "Tex.touchpad-blank", - - disable_defaultTextureLayer: "blank", - disable_textureLayers: { - blank: { - defaultTextureURL: BASE_URL + "meshes/controller/vive_trackpad.fbx/Touchpad.fbm/touchpad-blank.jpg" - }, - teleport: { - defaultTextureURL: BASE_URL + "meshes/controller/vive_trackpad.fbx/Touchpad.fbm/touchpad-teleport-active-LG.jpg" - }, - arrows: { - defaultTextureURL: BASE_URL + "meshes/controller/vive_trackpad.fbx/Touchpad.fbm/touchpad-look-arrows.jpg" - } - } - }, - - trigger: { - type: "rotational", - modelURL: BASE_URL + "meshes/controller/vive_trigger.fbx", - input: Controller.Standard.LT, - naturalPosition: {"x":0.000004500150680541992,"y":-0.027690507471561432,"z":0.04830199480056763}, - naturalDimensions: {x: 0.019105, y: 0.022189, z: 0.01909}, - origin: { x: 0, y: -0.015, z: -0.00 }, - minValue: 0.0, - maxValue: 1.0, - axis: { x: -1, y: 0, z: 0 }, - maxAngle: 25, - - textureName: "Tex.black-trigger", - defaultTextureLayer: "normal", - textureLayers: { - normal: { - defaultTextureURL: BASE_URL + viveTriggerModelURL + "/Trigger.fbm/black.jpg" - }, - highlight: { - defaultTextureURL: BASE_URL + viveTriggerModelURL + "/Trigger.fbm/yellow.jpg" - } - } - }, - - l_grip: { - type: "static", - modelURL: BASE_URL + "meshes/controller/vive_l_grip.fbx", - naturalPosition: {"x":-0.01720449887216091,"y":-0.014324013143777847,"z":0.08714400231838226}, - naturalDimensions: {x: 0.010094, y: 0.015064, z: 0.029552} - }, - - r_grip: { - type: "static", - modelURL: BASE_URL + "meshes/controller/vive_r_grip.fbx", - naturalPosition: {"x":0.01720449887216091,"y":-0.014324013143777847,"z":0.08714400231838226}, - naturalDimensions: {x: 0.010083, y: 0.015064, z: 0.029552} - }, - - sys_button: { - type: "static", - modelURL: BASE_URL + "meshes/controller/vive_sys_button.fbx", - naturalPosition: {"x":0,"y":0.0020399854984134436,"z":0.08825899660587311}, - naturalDimensions: {x: 0.009986, y: 0.004282, z: 0.010264} - }, - - button: { - type: "static", - modelURL: BASE_URL + "meshes/controller/vive_button.fbx", - naturalPosition: {"x":0,"y":0.005480996798723936,"z":0.019918499514460564}, - naturalDimensions: {x: 0.009986, y: 0.004496, z: 0.010121} - }, - button2: { - type: "static", - modelURL: BASE_URL + "meshes/controller/vive_button.fbx", - naturalPosition: {"x":0,"y":0.005480996798723936,"z":0.019918499514460564}, - naturalDimensions: {x: 0.009986, y: 0.004496, z: 0.010121} - } - } - } - ] -}; - - -VIVE_CONTROLLER_CONFIGURATION_RIGHT = { - name: "Vive Right", - controllers: [ - { - modelURL: viveModelURL, - jointIndex: MyAvatar.getJointIndex("_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND"), - rotation: rightBaseRotation, - position: Vec3.multiplyQbyV(Quat.fromPitchYawRollDegrees(0, 0, -45), rightBasePosition), - - dimensions: viveNaturalDimensions, - - naturalPosition: { - x: 0, - y: -0.034076502197422087, - z: 0.06380049744620919 - }, - - parts: { - // DISABLED FOR NOW - /* - tips: { - type: "static", - modelURL: viveTipsModelURL, - naturalPosition: {"x":-0.004377640783786774,"y":-0.034371938556432724,"z":0.06769277155399323}, - naturalDimensions: {x: 0.191437, y: 0.094095, z: 0.085656}, - - textureName: "Tex.Blank", - - defaultTextureLayer: "blank", - textureLayers: { - blank: { - defaultTextureURL: TIP_TEXTURE_BASE_URL + "/Blank.png" - }, - trigger: { - defaultTextureURL: TIP_TEXTURE_BASE_URL + "/Trigger.png" - }, - arrows: { - defaultTextureURL: TIP_TEXTURE_BASE_URL + "/Rotate.png" - }, - grip: { - defaultTextureURL: TIP_TEXTURE_BASE_URL + "/Grip.png" - }, - teleport: { - defaultTextureURL: TIP_TEXTURE_BASE_URL + "/Teleport.png" - } - } - }, - */ - - // The touchpad type draws a dot indicating the current touch/thumb position - // and swaps in textures based on the thumb position. - touchpad: { - type: "touchpad", - modelURL: BASE_URL + "meshes/controller/vive_trackpad.fbx", - visibleInput: "Vive.RSTouch", - xInput: "Vive.RX", - yInput: "Vive.RY", - naturalPosition: { x: 0, y: 0.000979491975158453, z: 0.04872849956154823 }, - naturalDimensions: {x: 0.042824, y: 0.012537, z: 0.043115}, - minValue: 0.0, - maxValue: 1.0, - minPosition: { x: -0.035, y: 0.004, z: -0.005 }, - maxPosition: { x: -0.035, y: 0.004, z: -0.005 }, - disable_textureName: "Tex.touchpad-blank", - - disable_defaultTextureLayer: "blank", - disable_textureLayers: { - blank: { - defaultTextureURL: BASE_URL + "meshes/controller/vive_trackpad.fbx/Touchpad.fbm/touchpad-blank.jpg" - }, - teleport: { - defaultTextureURL: BASE_URL + "meshes/controller/vive_trackpad.fbx/Touchpad.fbm/touchpad-teleport-active-LG.jpg" - }, - arrows: { - defaultTextureURL: BASE_URL + "meshes/controller/vive_trackpad.fbx/Touchpad.fbm/touchpad-look-arrows-active.jpg" - } - } - }, - - trigger: { - type: "rotational", - modelURL: BASE_URL + "meshes/controller/vive_trigger.fbx", - input: Controller.Standard.RT, - naturalPosition: {"x":0.000004500150680541992,"y":-0.027690507471561432,"z":0.04830199480056763}, - naturalDimensions: {x: 0.019105, y: 0.022189, z: 0.01909}, - origin: { x: 0, y: -0.015, z: -0.00 }, - minValue: 0.0, - maxValue: 1.0, - axis: { x: -1, y: 0, z: 0 }, - maxAngle: 25, - - textureName: "Tex.black-trigger", - defaultTextureLayer: "normal", - textureLayers: { - normal: { - defaultTextureURL: BASE_URL + viveTriggerModelURL + "/Trigger.fbm/black.jpg" - }, - highlight: { - defaultTextureURL: BASE_URL + viveTriggerModelURL + "/Trigger.fbm/yellow.jpg" - } - } - }, - - l_grip: { - type: "static", - modelURL: BASE_URL + "meshes/controller/vive_l_grip.fbx", - naturalPosition: {"x":-0.01720449887216091,"y":-0.014324013143777847,"z":0.08714400231838226}, - naturalDimensions: {x: 0.010094, y: 0.015064, z: 0.029552} - }, - - r_grip: { - type: "static", - modelURL: BASE_URL + "meshes/controller/vive_r_grip.fbx", - naturalPosition: {"x":0.01720449887216091,"y":-0.014324013143777847,"z":0.08714400231838226}, - naturalDimensions: {x: 0.010083, y: 0.015064, z: 0.029552} - }, - - sys_button: { - type: "static", - modelURL: BASE_URL + "meshes/controller/vive_sys_button.fbx", - naturalPosition: {"x":0,"y":0.0020399854984134436,"z":0.08825899660587311}, - naturalDimensions: {x: 0.009986, y: 0.004282, z: 0.010264} - }, - - button: { - type: "static", - modelURL: BASE_URL + "meshes/controller/vive_button.fbx", - naturalPosition: {"x":0,"y":0.005480996798723936,"z":0.019918499514460564}, - naturalDimensions: {x: 0.009986, y: 0.004496, z: 0.010121} - }, - button2: { - type: "static", - modelURL: BASE_URL + "meshes/controller/vive_button.fbx", - naturalPosition: {"x":0,"y":0.005480996798723936,"z":0.019918499514460564}, - naturalDimensions: {x: 0.009986, y: 0.004496, z: 0.010121} - } - } - } - ] -}; diff --git a/scripts/simplifiedUI/system/create/Edit.qml b/scripts/simplifiedUI/system/create/Edit.qml deleted file mode 100644 index ca18388def..0000000000 --- a/scripts/simplifiedUI/system/create/Edit.qml +++ /dev/null @@ -1,60 +0,0 @@ -import QtQuick 2.7 -import QtQuick.Controls 2.3 - -StackView { - id: editRoot - objectName: "stack" - - signal sendToScript(var message); - - topPadding: 40 - leftPadding: 0 - rightPadding: 0 - bottomPadding: 0 - - property var itemProperties: {"y": editRoot.topPadding, - "width": editRoot.availableWidth, - "height": editRoot.availableHeight } - Component.onCompleted: { - tab.currentIndex = 0 - } - - background: Rectangle { - color: "#404040" //default background color - EditTabView { - id: tab - anchors.fill: parent - currentIndex: -1 - onCurrentIndexChanged: { - editRoot.replace(null, tab.itemAt(currentIndex).visualItem, - itemProperties, - StackView.Immediate) - } - } - } - - function pushSource(path) { - var item = Qt.createComponent(Qt.resolvedUrl("../../" + path)); - editRoot.push(item, itemProperties, - StackView.Immediate); - editRoot.currentItem.sendToScript.connect(editRoot.sendToScript); - } - - function popSource() { - editRoot.pop(StackView.Immediate); - } - - // Passes script messages to the item on the top of the stack - function fromScript(message) { - var currentItem = editRoot.currentItem; - if (currentItem && currentItem.fromScript) - currentItem.fromScript(message); - } - - Component.onDestruction: { - if (KeyboardScriptingInterface.raised) { - KeyboardScriptingInterface.raised = false; - } - } -} - diff --git a/scripts/simplifiedUI/system/create/NewMaterialDialog.qml b/scripts/simplifiedUI/system/create/NewMaterialDialog.qml deleted file mode 100644 index 75570327e0..0000000000 --- a/scripts/simplifiedUI/system/create/NewMaterialDialog.qml +++ /dev/null @@ -1,178 +0,0 @@ -// -// NewMaterialDialog.qml -// qml/hifi -// -// Created by Sam Gondelman on 1/17/18 -// Copyright 2018 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -import QtQuick 2.7 -import QtQuick.Controls 2.2 -import QtQuick.Dialogs 1.2 as OriginalDialogs - -import stylesUit 1.0 -import controlsUit 1.0 -import dialogs 1.0 - -Rectangle { - id: newMaterialDialog - // width: parent.width - // height: parent.height - HifiConstants { id: hifi } - color: hifi.colors.baseGray; - signal sendToScript(var message); - property bool keyboardEnabled: false - property bool punctuationMode: false - property bool keyboardRasied: false - - function errorMessageBox(message) { - try { - return desktop.messageBox({ - icon: hifi.icons.warning, - defaultButton: OriginalDialogs.StandardButton.Ok, - title: "Error", - text: message - }); - } catch(e) { - Window.alert(message); - } - } - - Item { - id: column1 - anchors.rightMargin: 10 - anchors.leftMargin: 10 - anchors.bottomMargin: 10 - anchors.topMargin: 10 - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: keyboard.top - - Text { - id: text1 - text: qsTr("Material URL") - color: "#ffffff" - font.pixelSize: 12 - } - - TextInput { - id: materialURL - height: 20 - text: qsTr("") - color: "white" - anchors.top: text1.bottom - anchors.topMargin: 5 - anchors.left: parent.left - anchors.leftMargin: 0 - anchors.right: parent.right - anchors.rightMargin: 0 - font.pixelSize: 12 - - onAccepted: { - newMaterialDialog.keyboardEnabled = false; - } - - MouseArea { - anchors.fill: parent - onClicked: { - newMaterialDialog.keyboardEnabled = HMD.active - parent.focus = true; - parent.forceActiveFocus(); - materialURL.cursorPosition = materialURL.positionAt(mouseX, mouseY, TextInput.CursorBetweenCharaters); - } - } - } - - Rectangle { - id: textInputBox - color: "white" - anchors.fill: materialURL - opacity: 0.1 - } - - Row { - id: row1 - height: 400 - spacing: 30 - anchors.top: materialURL.bottom - anchors.topMargin: 5 - anchors.left: parent.left - anchors.leftMargin: 0 - anchors.right: parent.right - anchors.rightMargin: 0 - - Column { - id: column3 - height: 400 - spacing: 10 - - /*Text { - id: text3 - text: qsTr("Material Mode") - color: "#ffffff" - font.pixelSize: 12 - } - - ComboBox { - id: materialMappingMode - property var materialArray: ["UV space material", - "3D projected material"] - - width: 200 - z: 100 - transformOrigin: Item.Center - model: materialArray - }*/ - - Row { - id: row3 - width: 200 - height: 400 - spacing: 5 - - anchors.horizontalCenter: column3.horizontalCenter - anchors.horizontalCenterOffset: 0 - - Button { - id: button1 - text: qsTr("Add") - z: -1 - onClicked: { - newMaterialDialog.sendToScript({ - method: "newMaterialDialogAdd", - params: { - textInput: materialURL.text, - //comboBox: materialMappingMode.currentIndex - } - }); - } - } - - Button { - id: button2 - z: -1 - text: qsTr("Cancel") - onClicked: { - newMaterialDialog.sendToScript({method: "newMaterialDialogCancel"}) - } - } - } - } - } - } - - Keyboard { - id: keyboard - raised: parent.keyboardEnabled - numeric: parent.punctuationMode - anchors { - bottom: parent.bottom - left: parent.left - right: parent.right - } - } -} diff --git a/scripts/simplifiedUI/system/create/NewModelDialog.qml b/scripts/simplifiedUI/system/create/NewModelDialog.qml deleted file mode 100644 index 1ded00d701..0000000000 --- a/scripts/simplifiedUI/system/create/NewModelDialog.qml +++ /dev/null @@ -1,258 +0,0 @@ -// -// NewModelDialog.qml -// qml/hifi -// -// Created by Seth Alves on 2017-2-10 -// Copyright 2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -import QtQuick 2.5 -import QtQuick.Dialogs 1.2 as OriginalDialogs - -import stylesUit 1.0 -import controlsUit 1.0 -import dialogs 1.0 - -Rectangle { - id: newModelDialog - // width: parent.width - // height: parent.height - HifiConstants { id: hifi } - color: hifi.colors.baseGray; - signal sendToScript(var message); - property bool keyboardEnabled: false - property bool keyboardRaised: false - property bool punctuationMode: false - property bool keyboardRasied: false - - function errorMessageBox(message) { - try { - return desktop.messageBox({ - icon: hifi.icons.warning, - defaultButton: OriginalDialogs.StandardButton.Ok, - title: "Error", - text: message - }); - } catch(e) { - Window.alert(message); - } - } - - Item { - id: column1 - anchors.rightMargin: 10 - anchors.leftMargin: 10 - anchors.bottomMargin: 10 - anchors.topMargin: 10 - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: keyboard.top - - Text { - id: text1 - text: qsTr("Model URL") - color: "#ffffff" - font.pixelSize: 12 - } - - TextInput { - id: modelURL - height: 20 - text: qsTr("") - color: "white" - anchors.top: text1.bottom - anchors.topMargin: 5 - anchors.left: parent.left - anchors.leftMargin: 0 - anchors.right: parent.right - anchors.rightMargin: 0 - font.pixelSize: 12 - - onAccepted: { - newModelDialog.keyboardEnabled = false; - } - - onTextChanged : { - if (modelURL.text.length === 0){ - button1.enabled = false; - } else { - button1.enabled = true; - } - } - - MouseArea { - anchors.fill: parent - onClicked: { - newModelDialog.keyboardEnabled = HMD.active - parent.focus = true; - parent.forceActiveFocus(); - modelURL.cursorPosition = modelURL.positionAt(mouseX, mouseY, TextInput.CursorBetweenCharaters); - } - } - } - - Rectangle { - id: textInputBox - color: "white" - anchors.fill: modelURL - opacity: 0.1 - } - - Row { - id: row1 - height: 400 - spacing: 30 - anchors.top: modelURL.top - anchors.topMargin: 25 - anchors.left: parent.left - anchors.leftMargin: 0 - anchors.right: parent.right - anchors.rightMargin: 0 - - Column { - id: column2 - width: 200 - height: 600 - spacing: 10 - - CheckBox { - id: grabbable - text: qsTr("Grabbable") - } - - CheckBox { - id: dynamic - text: qsTr("Dynamic") - } - - Row { - id: row2 - width: 200 - height: 400 - spacing: 20 - - Image { - id: image1 - width: 30 - height: 30 - source: "qrc:/qtquickplugin/images/template_image.png" - } - - Text { - id: text2 - width: 160 - x: dynamic.width / 2 - color: "#ffffff" - text: qsTr("Models with automatic collisions set to 'Exact' cannot be dynamic, and should not be used as floors") - wrapMode: Text.WordWrap - font.pixelSize: 12 - } - } - } - - Column { - id: column3 - height: 400 - spacing: 10 - - Text { - id: text3 - text: qsTr("Automatic Collisions") - color: "#ffffff" - font.pixelSize: 12 - } - - ComboBox { - id: collisionType - - property int priorIndex: 0 - property string staticMeshCollisionText: "Exact - All polygons" - property var collisionArray: ["No Collision", - "Basic - Whole model", - "Good - Sub-meshes", - staticMeshCollisionText, - "Box", - "Sphere"] - - width: 200 - z: 100 - transformOrigin: Item.Center - model: collisionArray - - onCurrentIndexChanged: { - if (collisionArray[currentIndex] === staticMeshCollisionText) { - - if (dynamic.checked) { - currentIndex = priorIndex; - - errorMessageBox("Models with Automatic Collisions set to \"" - + staticMeshCollisionText + "\" cannot be dynamic."); - //--EARLY EXIT--( Can't have a static mesh model that's dynamic ) - return; - } - - dynamic.enabled = false; - } else { - dynamic.enabled = true; - } - - priorIndex = currentIndex; - } - } - - Row { - id: row3 - width: 200 - height: 400 - spacing: 5 - - anchors.horizontalCenter: column3.horizontalCenter - anchors.horizontalCenterOffset: -20 - - Button { - id: button1 - text: qsTr("Add") - z: -1 - enabled: false - onClicked: { - newModelDialog.sendToScript({ - method: "newModelDialogAdd", - params: { - url: modelURL.text, - dynamic: dynamic.checked, - collisionShapeIndex: collisionType.currentIndex, - grabbable: grabbable.checked - } - }); - } - } - - Button { - id: button2 - z: -1 - text: qsTr("Cancel") - onClicked: { - newModelDialog.sendToScript({method: "newModelDialogCancel"}) - } - } - } - } - } - } - - Keyboard { - id: keyboard - raised: parent.keyboardEnabled && parent.keyboardRaised - numeric: parent.punctuationMode - anchors { - bottom: parent.bottom - bottomMargin: 40 - left: parent.left - right: parent.right - } - } -} diff --git a/scripts/simplifiedUI/system/dialTone.js b/scripts/simplifiedUI/system/dialTone.js deleted file mode 100644 index 7c0a5b250d..0000000000 --- a/scripts/simplifiedUI/system/dialTone.js +++ /dev/null @@ -1,36 +0,0 @@ -"use strict"; - -// -// dialTone.js -// examples -// -// Created by Stephen Birarda on 06/08/15. -// Added disconnect HRS 6/11/15. -// Copyright 2015 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 -// - -(function() { // BEGIN LOCAL_SCOPE - -// setup the local sound we're going to use -var connectSound = SoundCache.getSound(Script.resolvePath("assets/sounds/hello.wav")); -var disconnectSound = SoundCache.getSound(Script.resolvePath("assets/sounds/goodbye.wav")); -var micMutedSound = SoundCache.getSound(Script.resolvePath("assets/sounds/goodbye.wav")); - -// setup the options needed for that sound -var soundOptions = { - localOnly: true -}; - -// play the sound locally once we get the first audio packet from a mixer -Audio.receivedFirstPacket.connect(function(){ - Audio.playSound(connectSound, soundOptions); -}); - -Audio.disconnected.connect(function(){ - Audio.playSound(disconnectSound, soundOptions); -}); - -}()); // END LOCAL_SCOPE diff --git a/scripts/simplifiedUI/system/directory.js b/scripts/simplifiedUI/system/directory.js deleted file mode 100644 index f84429ab95..0000000000 --- a/scripts/simplifiedUI/system/directory.js +++ /dev/null @@ -1,134 +0,0 @@ -// -// directory.js -// examples -// -// Created by David Rowe on 8 Jun 2015 -// Copyright 2015 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 -// - -Script.include([ - "libraries/toolBars.js", -]); - -var toolIconUrl = Script.resolvePath("assets/images/tools/"); - -var DIRECTORY_WINDOW_URL = Account.metaverseServerURL + "/directory"; -var directoryWindow = new OverlayWebWindow({ - title: 'Directory', - source: "about:blank", - width: 900, - height: 700, - visible: false -}); - -var toolHeight = 50; -var toolWidth = 50; -var TOOLBAR_MARGIN_Y = 0; - - -function showDirectory() { - directoryWindow.setURL(DIRECTORY_WINDOW_URL); - directoryWindow.setVisible(true); -} - -function hideDirectory() { - directoryWindow.setVisible(false); - directoryWindow.setURL("about:blank"); -} - -function toggleDirectory() { - if (directoryWindow.visible) { - hideDirectory(); - } else { - showDirectory(); - } -} - -var toolBar = (function() { - var that = {}, - toolBar, - browseDirectoryButton; - - function initialize() { - toolBar = new ToolBar(0, 0, ToolBar.HORIZONTAL, "highfidelity.directory.toolbar", function(windowDimensions, toolbar) { - return { - x: windowDimensions.x / 2, - y: windowDimensions.y - }; - }, { - x: -2 * toolWidth, - y: -TOOLBAR_MARGIN_Y - toolHeight - }); - browseDirectoryButton = toolBar.addTool({ - imageURL: toolIconUrl + "directory.svg", - subImage: { - x: 0, - y: Tool.IMAGE_WIDTH, - width: Tool.IMAGE_WIDTH, - height: Tool.IMAGE_HEIGHT - }, - width: toolWidth, - height: toolHeight, - alpha: 0.9, - visible: true - }); - - toolBar.showTool(browseDirectoryButton, true); - } - - var browseDirectoryButtonDown = false; - that.mousePressEvent = function(event) { - var clickedOverlay, - url, - file; - - if (!event.isLeftButton) { - // if another mouse button than left is pressed ignore it - return false; - } - - clickedOverlay = Overlays.getOverlayAtPoint({ - x: event.x, - y: event.y - }); - - - - if (browseDirectoryButton === toolBar.clicked(clickedOverlay)) { - toggleDirectory(); - return true; - } - - return false; - }; - - that.mouseReleaseEvent = function(event) { - var handled = false; - - - if (browseDirectoryButtonDown) { - var clickedOverlay = Overlays.getOverlayAtPoint({ - x: event.x, - y: event.y - }); - } - - newModelButtonDown = false; - browseDirectoryButtonDown = false; - - return handled; - } - - that.cleanup = function() { - toolBar.cleanup(); - }; - - initialize(); - return that; -}()); - -Controller.mousePressEvent.connect(toolBar.mousePressEvent) -Script.scriptEnding.connect(toolBar.cleanup); diff --git a/scripts/simplifiedUI/system/edit.js b/scripts/simplifiedUI/system/edit.js deleted file mode 100644 index cf99f3a618..0000000000 --- a/scripts/simplifiedUI/system/edit.js +++ /dev/null @@ -1,2858 +0,0 @@ -// edit.js -// -// Created by Brad Hefta-Gaub on 10/2/14. -// Persist toolbar by HRS 6/11/15. -// Copyright 2014 High Fidelity, Inc. -// -// This script allows you to edit entities with a new UI/UX for mouse and trackpad based editing -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -/* global Script, SelectionDisplay, LightOverlayManager, CameraManager, Grid, GridTool, EntityListTool, Vec3, SelectionManager, - Overlays, OverlayWebWindow, UserActivityLogger, Settings, Entities, Tablet, Toolbars, Messages, Menu, Camera, - progressDialog, tooltip, MyAvatar, Quat, Controller, Clipboard, HMD, UndoStack, OverlaySystemWindow, - keyUpEventFromUIWindow:true */ - -(function() { // BEGIN LOCAL_SCOPE - -"use strict"; - -var EDIT_TOGGLE_BUTTON = "com.highfidelity.interface.system.editButton"; - -var CONTROLLER_MAPPING_NAME = "com.highfidelity.editMode"; - -Script.include([ - "libraries/stringHelpers.js", - "libraries/dataViewHelpers.js", - "libraries/progressDialog.js", - "libraries/entitySelectionTool.js", - "libraries/ToolTip.js", - "libraries/entityCameraTool.js", - "libraries/gridTool.js", - "libraries/entityList.js", - "libraries/utils.js", - "libraries/entityIconOverlayManager.js" -]); - -var CreateWindow = Script.require('./modules/createWindow.js'); - -var TITLE_OFFSET = 60; -var CREATE_TOOLS_WIDTH = 490; -var MAX_DEFAULT_ENTITY_LIST_HEIGHT = 942; - -var DEFAULT_IMAGE = "https://hifi-content.s3.amazonaws.com/DomainContent/production/no-image.jpg"; - -var createToolsWindow = new CreateWindow( - Script.resolvePath("create/EditTools.qml"), - 'Create Tools', - 'com.highfidelity.create.createToolsWindow', - function () { - var windowHeight = Window.innerHeight - TITLE_OFFSET; - if (windowHeight > MAX_DEFAULT_ENTITY_LIST_HEIGHT) { - windowHeight = MAX_DEFAULT_ENTITY_LIST_HEIGHT; - } - return { - size: { - x: CREATE_TOOLS_WIDTH, - y: windowHeight - }, - position: { - x: Window.x + Window.innerWidth - CREATE_TOOLS_WIDTH, - y: Window.y + TITLE_OFFSET - } - } - }, - false -); - -/** - * @description Returns true in case we should use the tablet version of the CreateApp - * @returns boolean - */ -var shouldUseEditTabletApp = function() { - return HMD.active || (!HMD.active && !Settings.getValue("desktopTabletBecomesToolbar", true)); -}; - - -var selectionDisplay = SelectionDisplay; -var selectionManager = SelectionManager; - -var PARTICLE_SYSTEM_URL = Script.resolvePath("assets/images/icon-particles.svg"); -var POINT_LIGHT_URL = Script.resolvePath("assets/images/icon-point-light.svg"); -var SPOT_LIGHT_URL = Script.resolvePath("assets/images/icon-spot-light.svg"); -var ZONE_URL = Script.resolvePath("assets/images/icon-zone.svg"); - -var entityIconOverlayManager = new EntityIconOverlayManager(['Light', 'ParticleEffect', 'Zone'], function(entityID) { - var properties = Entities.getEntityProperties(entityID, ['type', 'isSpotlight']); - if (properties.type === 'Light') { - return { - url: properties.isSpotlight ? SPOT_LIGHT_URL : POINT_LIGHT_URL, - }; - } else if (properties.type === 'Zone') { - return { - url: ZONE_URL, - }; - } else { - return { - url: PARTICLE_SYSTEM_URL, - }; - } -}); - -var cameraManager = new CameraManager(); - -var grid = new Grid(); -var gridTool = new GridTool({ - horizontalGrid: grid, - createToolsWindow: createToolsWindow, - shouldUseEditTabletApp: shouldUseEditTabletApp -}); -gridTool.setVisible(false); - -var EntityShapeVisualizer = Script.require('./modules/entityShapeVisualizer.js'); -var entityShapeVisualizer = new EntityShapeVisualizer(["Zone"]); - -var entityListTool = new EntityListTool(shouldUseEditTabletApp); - -selectionManager.addEventListener(function () { - selectionDisplay.updateHandles(); - entityIconOverlayManager.updatePositions(); - entityShapeVisualizer.setEntities(selectionManager.selections); -}); - -var DEGREES_TO_RADIANS = Math.PI / 180.0; -var RADIANS_TO_DEGREES = 180.0 / Math.PI; - -var MIN_ANGULAR_SIZE = 2; -var MAX_ANGULAR_SIZE = 45; -var allowLargeModels = true; -var allowSmallModels = true; - -var DEFAULT_DIMENSION = 0.20; - -var DEFAULT_DIMENSIONS = { - x: DEFAULT_DIMENSION, - y: DEFAULT_DIMENSION, - z: DEFAULT_DIMENSION -}; - -var DEFAULT_LIGHT_DIMENSIONS = Vec3.multiply(20, DEFAULT_DIMENSIONS); - -var MENU_AUTO_FOCUS_ON_SELECT = "Auto Focus on Select"; -var MENU_EASE_ON_FOCUS = "Ease Orientation on Focus"; -var MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE = "Show Lights and Particle Systems in Create Mode"; -var MENU_SHOW_ZONES_IN_EDIT_MODE = "Show Zones in Create Mode"; - -var MENU_CREATE_ENTITIES_GRABBABLE = "Create Entities As Grabbable (except Zones, Particles, and Lights)"; -var MENU_ALLOW_SELECTION_LARGE = "Allow Selecting of Large Models"; -var MENU_ALLOW_SELECTION_SMALL = "Allow Selecting of Small Models"; -var MENU_ALLOW_SELECTION_LIGHTS = "Allow Selecting of Lights"; - -var SETTING_AUTO_FOCUS_ON_SELECT = "autoFocusOnSelect"; -var SETTING_EASE_ON_FOCUS = "cameraEaseOnFocus"; -var SETTING_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE = "showLightsAndParticlesInEditMode"; -var SETTING_SHOW_ZONES_IN_EDIT_MODE = "showZonesInEditMode"; - -var SETTING_EDIT_PREFIX = "Edit/"; - - -var CREATE_ENABLED_ICON = "icons/tablet-icons/edit-i.svg"; -var CREATE_DISABLED_ICON = "icons/tablet-icons/edit-disabled.svg"; - -// marketplace info, etc. not quite ready yet. -var SHOULD_SHOW_PROPERTY_MENU = false; -var INSUFFICIENT_PERMISSIONS_ERROR_MSG = "You do not have the necessary permissions to edit on this domain."; -var INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG = "You do not have the necessary permissions to place items on this domain."; - -var isActive = false; -var createButton = null; - -var IMPORTING_SVO_OVERLAY_WIDTH = 144; -var IMPORTING_SVO_OVERLAY_HEIGHT = 30; -var IMPORTING_SVO_OVERLAY_MARGIN = 5; -var IMPORTING_SVO_OVERLAY_LEFT_MARGIN = 34; -var importingSVOImageOverlay = Overlays.addOverlay("image", { - imageURL: Script.resolvePath("assets") + "/images/hourglass.svg", - width: 20, - height: 20, - alpha: 1.0, - x: Window.innerWidth - IMPORTING_SVO_OVERLAY_WIDTH, - y: Window.innerHeight - IMPORTING_SVO_OVERLAY_HEIGHT, - visible: false -}); -var importingSVOTextOverlay = Overlays.addOverlay("text", { - font: { - size: 14 - }, - text: "Importing SVO...", - leftMargin: IMPORTING_SVO_OVERLAY_LEFT_MARGIN, - x: Window.innerWidth - IMPORTING_SVO_OVERLAY_WIDTH - IMPORTING_SVO_OVERLAY_MARGIN, - y: Window.innerHeight - IMPORTING_SVO_OVERLAY_HEIGHT - IMPORTING_SVO_OVERLAY_MARGIN, - width: IMPORTING_SVO_OVERLAY_WIDTH, - height: IMPORTING_SVO_OVERLAY_HEIGHT, - backgroundColor: { - red: 80, - green: 80, - blue: 80 - }, - backgroundAlpha: 0.7, - visible: false -}); - -var MARKETPLACE_URL = Account.metaverseServerURL + "/marketplace"; -var marketplaceWindow = new OverlayWebWindow({ - title: 'Marketplace', - source: "about:blank", - width: 900, - height: 700, - visible: false -}); - -function showMarketplace(marketplaceID) { - var url = MARKETPLACE_URL; - if (marketplaceID) { - url = url + "/items/" + marketplaceID; - } - marketplaceWindow.setURL(url); - marketplaceWindow.setVisible(true); - marketplaceWindow.raise(); - - UserActivityLogger.logAction("opened_marketplace"); -} - -function hideMarketplace() { - marketplaceWindow.setVisible(false); - marketplaceWindow.setURL("about:blank"); -} - -// function toggleMarketplace() { -// if (marketplaceWindow.visible) { -// hideMarketplace(); -// } else { -// showMarketplace(); -// } -// } - -function adjustPositionPerBoundingBox(position, direction, registration, dimensions, orientation) { - // Adjust the position such that the bounding box (registration, dimensions and orientation) lies behind the original - // position in the given direction. - var CORNERS = [ - { x: 0, y: 0, z: 0 }, - { x: 0, y: 0, z: 1 }, - { x: 0, y: 1, z: 0 }, - { x: 0, y: 1, z: 1 }, - { x: 1, y: 0, z: 0 }, - { x: 1, y: 0, z: 1 }, - { x: 1, y: 1, z: 0 }, - { x: 1, y: 1, z: 1 }, - ]; - - // Go through all corners and find least (most negative) distance in front of position. - var distance = 0; - for (var i = 0, length = CORNERS.length; i < length; i++) { - var cornerVector = - Vec3.multiplyQbyV(orientation, Vec3.multiplyVbyV(Vec3.subtract(CORNERS[i], registration), dimensions)); - var cornerDistance = Vec3.dot(cornerVector, direction); - distance = Math.min(cornerDistance, distance); - } - position = Vec3.sum(Vec3.multiply(distance, direction), position); - return position; -} - -var GRABBABLE_ENTITIES_MENU_CATEGORY = "Edit"; - -// Handles any edit mode updates required when domains have switched -function checkEditPermissionsAndUpdate() { - if ((createButton === null) || (createButton === undefined)) { - //--EARLY EXIT--( nothing to safely update ) - return; - } - - var hasRezPermissions = (Entities.canRez() || Entities.canRezTmp() || Entities.canRezCertified() || Entities.canRezTmpCertified()); - createButton.editProperties({ - icon: (hasRezPermissions ? CREATE_ENABLED_ICON : CREATE_DISABLED_ICON), - captionColor: (hasRezPermissions ? "#ffffff" : "#888888"), - }); - - if (!hasRezPermissions && isActive) { - that.setActive(false); - tablet.gotoHomeScreen(); - } -} - -// Copies the properties in `b` into `a`. `a` will be modified. -function copyProperties(a, b) { - for (var key in b) { - a[key] = b[key]; - } - return a; -} - -const DEFAULT_DYNAMIC_PROPERTIES = { - dynamic: true, - damping: 0.39347, - angularDamping: 0.39347, - gravity: { x: 0, y: -9.8, z: 0 }, -}; - -const DEFAULT_NON_DYNAMIC_PROPERTIES = { - dynamic: false, - damping: 0, - angularDamping: 0, - gravity: { x: 0, y: 0, z: 0 }, -}; - -const DEFAULT_ENTITY_PROPERTIES = { - All: { - description: "", - rotation: { x: 0, y: 0, z: 0, w: 1 }, - collidesWith: "static,dynamic,kinematic,otherAvatar,myAvatar", - collisionSoundURL: "", - cloneable: false, - ignoreIK: true, - canCastShadow: true, - href: "", - script: "", - serverScripts:"", - velocity: { - x: 0, - y: 0, - z: 0 - }, - angularVelocity: { - x: 0, - y: 0, - z: 0 - }, - restitution: 0.5, - friction: 0.5, - density: 1000, - dynamic: false, - }, - Shape: { - shape: "Box", - dimensions: { x: 0.2, y: 0.2, z: 0.2 }, - color: { red: 0, green: 180, blue: 239 }, - }, - Text: { - text: "Text", - dimensions: { - x: 0.65, - y: 0.3, - z: 0.01 - }, - textColor: { red: 255, green: 255, blue: 255 }, - backgroundColor: { red: 0, green: 0, blue: 0 }, - lineHeight: 0.06, - faceCamera: false, - }, - Zone: { - dimensions: { - x: 10, - y: 10, - z: 10 - }, - flyingAllowed: true, - ghostingAllowed: true, - filter: "", - keyLightMode: "inherit", - keyLightColor: { red: 255, green: 255, blue: 255 }, - keyLight: { - intensity: 1.0, - direction: { - x: 0.0, - y: -0.707106769084930, // 45 degrees - z: 0.7071067690849304 - }, - castShadows: true - }, - ambientLightMode: "inherit", - ambientLight: { - ambientIntensity: 0.5, - ambientURL: "" - }, - hazeMode: "inherit", - haze: { - hazeRange: 1000, - hazeAltitudeEffect: false, - hazeBaseRef: 0, - hazeColor: { - red: 128, - green: 154, - blue: 179 - }, - hazeBackgroundBlend: 0, - hazeEnableGlare: false, - hazeGlareColor: { - red: 255, - green: 229, - blue: 179 - }, - }, - shapeType: "box", - bloomMode: "inherit", - avatarPriority: "inherit" - }, - Model: { - collisionShape: "none", - compoundShapeURL: "", - animation: { - url: "", - running: false, - allowTranslation: false, - loop: true, - hold: false, - currentFrame: 0, - firstFrame: 0, - lastFrame: 100000, - fps: 30.0, - } - }, - Image: { - dimensions: { - x: 0.5385, - y: 0.2819, - z: 0.0092 - }, - shapeType: "box", - collisionless: true, - keepAspectRatio: false, - imageURL: DEFAULT_IMAGE - }, - Web: { - dimensions: { - x: 1.6, - y: 0.9, - z: 0.01 - }, - sourceUrl: "https://highfidelity.com/", - dpi: 30, - }, - ParticleEffect: { - lifespan: 1.5, - maxParticles: 10, - textures: "https://content.highfidelity.com/DomainContent/production/Particles/wispy-smoke.png", - emitRate: 5.5, - emitSpeed: 0, - speedSpread: 0, - emitDimensions: { x: 0, y: 0, z: 0 }, - emitOrientation: { x: 0, y: 0, z: 0, w: 1 }, - emitterShouldTrail: true, - particleRadius: 0.25, - radiusStart: 0, - radiusSpread: 0, - particleColor: { - red: 255, - green: 255, - blue: 255 - }, - colorSpread: { - red: 0, - green: 0, - blue: 0 - }, - alpha: 0, - alphaStart: 1, - alphaSpread: 0, - emitAcceleration: { - x: 0, - y: 2.5, - z: 0 - }, - accelerationSpread: { - x: 0, - y: 0, - z: 0 - }, - particleSpin: 0, - spinSpread: 0, - rotateWithEntity: false, - polarStart: 0, - polarFinish: Math.PI, - azimuthStart: -Math.PI, - azimuthFinish: Math.PI - }, - Light: { - color: { red: 255, green: 255, blue: 255 }, - intensity: 5.0, - dimensions: DEFAULT_LIGHT_DIMENSIONS, - falloffRadius: 1.0, - isSpotlight: false, - exponent: 1.0, - cutoff: 75.0, - }, -}; - -var toolBar = (function () { - var EDIT_SETTING = "io.highfidelity.isEditing"; // for communication with other scripts - var that = {}, - toolBar, - activeButton = null, - systemToolbar = null, - dialogWindow = null, - tablet = null; - - function createNewEntity(requestedProperties) { - var dimensions = requestedProperties.dimensions ? requestedProperties.dimensions : DEFAULT_DIMENSIONS; - var position = getPositionToCreateEntity(); - var entityID = null; - - var properties = {}; - - copyProperties(properties, DEFAULT_ENTITY_PROPERTIES.All); - - var type = requestedProperties.type; - if (type === "Box" || type === "Sphere") { - copyProperties(properties, DEFAULT_ENTITY_PROPERTIES.Shape); - } else { - copyProperties(properties, DEFAULT_ENTITY_PROPERTIES[type]); - } - - // We apply the requested properties first so that they take priority over any default properties. - copyProperties(properties, requestedProperties); - - if (properties.dynamic) { - copyProperties(properties, DEFAULT_DYNAMIC_PROPERTIES); - } else { - copyProperties(properties, DEFAULT_NON_DYNAMIC_PROPERTIES); - } - - - if (position !== null && position !== undefined) { - var direction; - if (Camera.mode === "entity" || Camera.mode === "independent") { - direction = Camera.orientation; - } else { - direction = MyAvatar.orientation; - } - direction = Vec3.multiplyQbyV(direction, Vec3.UNIT_Z); - - var PRE_ADJUST_ENTITY_TYPES = ["Box", "Sphere", "Shape", "Text", "Image", "Web", "Material"]; - if (PRE_ADJUST_ENTITY_TYPES.indexOf(properties.type) !== -1) { - - // Adjust position of entity per bounding box prior to creating it. - var registration = properties.registration; - if (registration === undefined) { - var DEFAULT_REGISTRATION = { x: 0.5, y: 0.5, z: 0.5 }; - registration = DEFAULT_REGISTRATION; - } - - var orientation = properties.orientation; - if (orientation === undefined) { - properties.orientation = MyAvatar.orientation; - var DEFAULT_ORIENTATION = properties.orientation; - orientation = DEFAULT_ORIENTATION; - } else { - // If the orientation is already defined, we perform the corresponding rotation assuming that - // our start referential is the avatar referential. - properties.orientation = Quat.multiply(MyAvatar.orientation, properties.orientation); - var DEFAULT_ORIENTATION = properties.orientation; - orientation = DEFAULT_ORIENTATION; - } - - position = adjustPositionPerBoundingBox(position, direction, registration, dimensions, orientation); - } - - position = grid.snapToSurface(grid.snapToGrid(position, false, dimensions), dimensions); - properties.position = position; - - if (!properties.grab) { - properties.grab = {}; - if (Menu.isOptionChecked(MENU_CREATE_ENTITIES_GRABBABLE) && - !(properties.type === "Zone" || properties.type === "Light" || properties.type === "ParticleEffect")) { - properties.grab.grabbable = true; - } else { - properties.grab.grabbable = false; - } - } - - entityID = Entities.addEntity(properties); - SelectionManager.addEntity(entityID, false, this); - SelectionManager.saveProperties(); - pushCommandForSelections([{ - entityID: entityID, - properties: properties - }], [], true); - - var POST_ADJUST_ENTITY_TYPES = ["Model"]; - if (POST_ADJUST_ENTITY_TYPES.indexOf(properties.type) !== -1) { - // Adjust position of entity per bounding box after it has been created and auto-resized. - var initialDimensions = Entities.getEntityProperties(entityID, ["dimensions"]).dimensions; - var DIMENSIONS_CHECK_INTERVAL = 200; - var MAX_DIMENSIONS_CHECKS = 10; - var dimensionsCheckCount = 0; - var dimensionsCheckFunction = function () { - dimensionsCheckCount++; - var properties = Entities.getEntityProperties(entityID, ["dimensions", "registrationPoint", "rotation"]); - if (!Vec3.equal(properties.dimensions, initialDimensions)) { - position = adjustPositionPerBoundingBox(position, direction, properties.registrationPoint, - properties.dimensions, properties.rotation); - position = grid.snapToSurface(grid.snapToGrid(position, false, properties.dimensions), - properties.dimensions); - Entities.editEntity(entityID, { - position: position - }); - selectionManager._update(false, this); - } else if (dimensionsCheckCount < MAX_DIMENSIONS_CHECKS) { - Script.setTimeout(dimensionsCheckFunction, DIMENSIONS_CHECK_INTERVAL); - } - }; - Script.setTimeout(dimensionsCheckFunction, DIMENSIONS_CHECK_INTERVAL); - } - } else { - Window.notifyEditError("Can't create " + properties.type + ": " + - properties.type + " would be out of bounds."); - } - - selectionManager.clearSelections(this); - entityListTool.sendUpdate(); - selectionManager.setSelections([entityID], this); - - Window.setFocus(); - - return entityID; - } - - function closeExistingDialogWindow() { - if (dialogWindow) { - dialogWindow.close(); - dialogWindow = null; - } - } - - function cleanup() { - that.setActive(false); - if (tablet) { - tablet.removeButton(activeButton); - } - if (systemToolbar) { - systemToolbar.removeButton(EDIT_TOGGLE_BUTTON); - } - } - - var buttonHandlers = {}; // only used to tablet mode - - function addButton(name, handler) { - buttonHandlers[name] = handler; - } - - var SHAPE_TYPE_NONE = 0; - var SHAPE_TYPE_SIMPLE_HULL = 1; - var SHAPE_TYPE_SIMPLE_COMPOUND = 2; - var SHAPE_TYPE_STATIC_MESH = 3; - var SHAPE_TYPE_BOX = 4; - var SHAPE_TYPE_SPHERE = 5; - var DYNAMIC_DEFAULT = false; - - var MATERIAL_MODE_UV = 0; - var MATERIAL_MODE_PROJECTED = 1; - - function handleNewModelDialogResult(result) { - if (result) { - var url = result.url; - var shapeType; - switch (result.collisionShapeIndex) { - case SHAPE_TYPE_SIMPLE_HULL: - shapeType = "simple-hull"; - break; - case SHAPE_TYPE_SIMPLE_COMPOUND: - shapeType = "simple-compound"; - break; - case SHAPE_TYPE_STATIC_MESH: - shapeType = "static-mesh"; - break; - case SHAPE_TYPE_BOX: - shapeType = "box"; - break; - case SHAPE_TYPE_SPHERE: - shapeType = "sphere"; - break; - default: - shapeType = "none"; - } - - var dynamic = result.dynamic !== null ? result.dynamic : DYNAMIC_DEFAULT; - if (shapeType === "static-mesh" && dynamic) { - // The prompt should prevent this case - print("Error: model cannot be both static mesh and dynamic. This should never happen."); - } else if (url) { - createNewEntity({ - type: "Model", - modelURL: url, - shapeType: shapeType, - grab: { - grabbable: result.grabbable - }, - dynamic: dynamic, - }); - } - } - } - - function handleNewMaterialDialogResult(result) { - if (result) { - var materialURL = result.textInput; - //var materialMappingMode; - //switch (result.comboBox) { - // case MATERIAL_MODE_PROJECTED: - // materialMappingMode = "projected"; - // break; - // default: - // shapeType = "uv"; - //} - var materialData = ""; - if (materialURL.startsWith("materialData")) { - materialData = JSON.stringify({ - "materials": {} - }); - } - - var DEFAULT_LAYERED_MATERIAL_PRIORITY = 1; - if (materialURL) { - createNewEntity({ - type: "Material", - materialURL: materialURL, - //materialMappingMode: materialMappingMode, - priority: DEFAULT_LAYERED_MATERIAL_PRIORITY, - materialData: materialData - }); - } - } - } - - function fromQml(message) { // messages are {method, params}, like json-rpc. See also sendToQml. - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - tablet.popFromStack(); - switch (message.method) { - case "newModelDialogAdd": - handleNewModelDialogResult(message.params); - closeExistingDialogWindow(); - break; - case "newModelDialogCancel": - closeExistingDialogWindow(); - break; - case "newEntityButtonClicked": - buttonHandlers[message.params.buttonName](); - break; - case "newMaterialDialogAdd": - handleNewMaterialDialogResult(message.params); - closeExistingDialogWindow(); - break; - case "newMaterialDialogCancel": - closeExistingDialogWindow(); - break; - } - } - - var entitiesToDelete = []; - var deletedEntityTimer = null; - var DELETE_ENTITY_TIMER_TIMEOUT = 100; - - function checkDeletedEntityAndUpdate(entityID) { - // Allow for multiple entity deletes before updating the entities selected. - entitiesToDelete.push(entityID); - if (deletedEntityTimer !== null) { - Script.clearTimeout(deletedEntityTimer); - } - deletedEntityTimer = Script.setTimeout(function () { - if (entitiesToDelete.length > 0) { - selectionManager.removeEntities(entitiesToDelete, this); - } - entityListTool.removeEntities(entitiesToDelete, selectionManager.selections); - entitiesToDelete = []; - deletedEntityTimer = null; - }, DELETE_ENTITY_TIMER_TIMEOUT); - } - - function initialize() { - Script.scriptEnding.connect(cleanup); - Window.domainChanged.connect(function () { - if (isActive) { - tablet.gotoHomeScreen(); - } - that.setActive(false); - that.clearEntityList(); - checkEditPermissionsAndUpdate(); - }); - - HMD.displayModeChanged.connect(function() { - if (isActive) { - tablet.gotoHomeScreen(); - } - that.setActive(false); - }); - - Entities.canAdjustLocksChanged.connect(function (canAdjustLocks) { - if (isActive && !canAdjustLocks) { - that.setActive(false); - } - checkEditPermissionsAndUpdate(); - }); - - Entities.canRezChanged.connect(checkEditPermissionsAndUpdate); - Entities.canRezTmpChanged.connect(checkEditPermissionsAndUpdate); - Entities.canRezCertifiedChanged.connect(checkEditPermissionsAndUpdate); - Entities.canRezTmpCertifiedChanged.connect(checkEditPermissionsAndUpdate); - var hasRezPermissions = (Entities.canRez() || Entities.canRezTmp() || Entities.canRezCertified() || Entities.canRezTmpCertified()); - - Entities.deletingEntity.connect(checkDeletedEntityAndUpdate); - - var createButtonIconRsrc = (hasRezPermissions ? CREATE_ENABLED_ICON : CREATE_DISABLED_ICON); - tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - activeButton = tablet.addButton({ - captionColor: hasRezPermissions ? "#ffffff" : "#888888", - icon: createButtonIconRsrc, - activeIcon: "icons/tablet-icons/edit-a.svg", - text: "CREATE", - sortOrder: 10 - }); - createButton = activeButton; - tablet.screenChanged.connect(function (type, url) { - var isGoingToHomescreenOnDesktop = (!shouldUseEditTabletApp() && - (url === 'hifi/tablet/TabletHome.qml' || url === '')); - if (isActive && (type !== "QML" || url !== Script.resolvePath("create/Edit.qml")) && !isGoingToHomescreenOnDesktop) { - that.setActive(false); - } - }); - tablet.fromQml.connect(fromQml); - createToolsWindow.fromQml.addListener(fromQml); - - createButton.clicked.connect(function() { - if ( ! (Entities.canRez() || Entities.canRezTmp() || Entities.canRezCertified() || Entities.canRezTmpCertified()) ) { - Window.notifyEditError(INSUFFICIENT_PERMISSIONS_ERROR_MSG); - return; - } - - that.toggle(); - }); - - addButton("importEntitiesButton", function() { - Window.browseChanged.connect(onFileOpenChanged); - Window.browseAsync("Select Model to Import", "", "*.json"); - }); - - addButton("openAssetBrowserButton", function() { - Window.showAssetServer(); - }); - function createNewEntityDialogButtonCallback(entityType) { - return function() { - if (shouldUseEditTabletApp()) { - // tablet version of new-model dialog - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - tablet.pushOntoStack(Script.resolvePath("create/New" + entityType + "Dialog.qml")); - } else { - closeExistingDialogWindow(); - var qmlPath = Script.resolvePath("create/New" + entityType + "Window.qml"); - var DIALOG_WINDOW_SIZE = { x: 500, y: 300 }; - dialogWindow = Desktop.createWindow(qmlPath, { - title: "New " + entityType + " Entity", - flags: Desktop.ALWAYS_ON_TOP | Desktop.CLOSE_BUTTON_HIDES, - presentationMode: Desktop.PresentationMode.NATIVE, - size: DIALOG_WINDOW_SIZE, - visible: true - }); - dialogWindow.fromQml.connect(fromQml); - } - }; - } - - addButton("newModelButton", createNewEntityDialogButtonCallback("Model")); - - addButton("newShapeButton", function () { - createNewEntity({ - type: "Shape", - shape: "Cube", - }); - }); - - addButton("newLightButton", function () { - createNewEntity({ - type: "Light", - }); - }); - - addButton("newTextButton", function () { - createNewEntity({ - type: "Text", - }); - }); - - addButton("newImageButton", function () { - createNewEntity({ - type: "Image", - }); - }); - - addButton("newWebButton", function () { - createNewEntity({ - type: "Web", - }); - }); - - addButton("newZoneButton", function () { - createNewEntity({ - type: "Zone", - }); - }); - - addButton("newParticleButton", function () { - createNewEntity({ - type: "ParticleEffect", - }); - }); - - addButton("newMaterialButton", createNewEntityDialogButtonCallback("Material")); - - var deactivateCreateIfDesktopWindowsHidden = function() { - if (!shouldUseEditTabletApp() && !entityListTool.isVisible() && !createToolsWindow.isVisible()) { - that.setActive(false); - } - }; - entityListTool.interactiveWindowHidden.addListener(this, deactivateCreateIfDesktopWindowsHidden); - createToolsWindow.interactiveWindowHidden.addListener(this, deactivateCreateIfDesktopWindowsHidden); - - that.setActive(false); - } - - that.clearEntityList = function () { - entityListTool.clearEntityList(); - }; - - that.toggle = function () { - that.setActive(!isActive); - if (!isActive) { - tablet.gotoHomeScreen(); - } - }; - - that.setActive = function (active) { - ContextOverlay.enabled = !active; - Settings.setValue(EDIT_SETTING, active); - if (active) { - Controller.captureEntityClickEvents(); - } else { - Controller.releaseEntityClickEvents(); - - closeExistingDialogWindow(); - } - if (active === isActive) { - return; - } - if (active && !Entities.canRez() && !Entities.canRezTmp() && !Entities.canRezCertified() && !Entities.canRezTmpCertified()) { - Window.notifyEditError(INSUFFICIENT_PERMISSIONS_ERROR_MSG); - return; - } - Messages.sendLocalMessage("edit-events", JSON.stringify({ - enabled: active - })); - isActive = active; - activeButton.editProperties({isActive: isActive}); - undoHistory.setEnabled(isActive); - - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - - if (!isActive) { - entityListTool.setVisible(false); - gridTool.setVisible(false); - grid.setEnabled(false); - propertiesTool.setVisible(false); - selectionManager.clearSelections(this); - cameraManager.disable(); - selectionDisplay.disableTriggerMapping(); - tablet.landscape = false; - Controller.disableMapping(CONTROLLER_MAPPING_NAME); - } else { - if (shouldUseEditTabletApp()) { - tablet.loadQMLSource(Script.resolvePath("create/Edit.qml"), true); - } else { - // make other apps inactive while in desktop mode - tablet.gotoHomeScreen(); - } - UserActivityLogger.enabledEdit(); - entityListTool.setVisible(true); - entityListTool.sendUpdate(); - gridTool.setVisible(true); - grid.setEnabled(true); - propertiesTool.setVisible(true); - selectionDisplay.enableTriggerMapping(); - print("starting tablet in landscape mode"); - tablet.landscape = true; - Controller.enableMapping(CONTROLLER_MAPPING_NAME); - // Not sure what the following was meant to accomplish, but it currently causes - // everybody else to think that Interface has lost focus overall. fogbugzid:558 - // Window.setFocus(); - } - entityIconOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE)); - Entities.setDrawZoneBoundaries(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE)); - }; - - initialize(); - return that; -})(); - -var selectedEntityID; -var orientation; -var intersection; - - -function rayPlaneIntersection(pickRay, point, normal) { // - // - // This version of the test returns the intersection of a line with a plane - // - var collides = Vec3.dot(pickRay.direction, normal); - - var d = -Vec3.dot(point, normal); - var t = -(Vec3.dot(pickRay.origin, normal) + d) / collides; - - return Vec3.sum(pickRay.origin, Vec3.multiply(pickRay.direction, t)); -} - -function rayPlaneIntersection2(pickRay, point, normal) { - // - // This version of the test returns false if the ray is directed away from the plane - // - var collides = Vec3.dot(pickRay.direction, normal); - var d = -Vec3.dot(point, normal); - var t = -(Vec3.dot(pickRay.origin, normal) + d) / collides; - if (t < 0.0) { - return false; - } else { - return Vec3.sum(pickRay.origin, Vec3.multiply(pickRay.direction, t)); - } -} - -function findClickedEntity(event) { - var pickZones = event.isControl; - - if (pickZones) { - Entities.setZonesArePickable(true); - } - - var pickRay = Camera.computePickRay(event.x, event.y); - var tabletIDs = getMainTabletIDs(); - if (tabletIDs.length > 0) { - var overlayResult = Overlays.findRayIntersection(pickRay, true, tabletIDs); - if (overlayResult.intersects) { - return null; - } - } - - var entityResult = Entities.findRayIntersection(pickRay, true); // want precision picking - var iconResult = entityIconOverlayManager.findRayIntersection(pickRay); - iconResult.accurate = true; - - if (pickZones) { - Entities.setZonesArePickable(false); - } - - var result; - - if (iconResult.intersects) { - result = iconResult; - } else if (entityResult.intersects) { - result = entityResult; - } else { - return null; - } - - if (!result.accurate) { - return null; - } - - var foundEntity = result.entityID; - return { - pickRay: pickRay, - entityID: foundEntity, - intersection: result.intersection - }; -} - -// Handles selections on overlays while in edit mode by querying entities from -// entityIconOverlayManager. -function handleOverlaySelectionToolUpdates(channel, message, sender) { - var wantDebug = false; - if (sender !== MyAvatar.sessionUUID || channel !== 'entityToolUpdates') - return; - - var data = JSON.parse(message); - - if (data.method === "selectOverlay") { - if (!selectionDisplay.triggered() || selectionDisplay.triggeredHand === data.hand) { - if (wantDebug) { - print("setting selection to overlay " + data.overlayID); - } - var entity = entityIconOverlayManager.findEntity(data.overlayID); - - if (entity !== null) { - selectionManager.setSelections([entity], this); - } - } - } -} - -function handleMessagesReceived(channel, message, sender) { - switch( channel ){ - case 'entityToolUpdates': { - handleOverlaySelectionToolUpdates( channel, message, sender ); - break; - } - default: { - return; - } - } -} - -Messages.subscribe("entityToolUpdates"); -Messages.messageReceived.connect(handleMessagesReceived); - -var mouseHasMovedSincePress = false; -var mousePressStartTime = 0; -var mousePressStartPosition = { - x: 0, - y: 0 -}; -var mouseDown = false; - -function mousePressEvent(event) { - mouseDown = true; - mousePressStartPosition = { - x: event.x, - y: event.y - }; - mousePressStartTime = Date.now(); - mouseHasMovedSincePress = false; - mouseCapturedByTool = false; - - if (propertyMenu.mousePressEvent(event) || progressDialog.mousePressEvent(event)) { - mouseCapturedByTool = true; - return; - } - if (isActive) { - if (cameraManager.mousePressEvent(event) || selectionDisplay.mousePressEvent(event)) { - // Event handled; do nothing. - return; - } - } -} - -var mouseCapturedByTool = false; -var lastMousePosition = null; -var CLICK_TIME_THRESHOLD = 500 * 1000; // 500 ms -var CLICK_MOVE_DISTANCE_THRESHOLD = 20; -var IDLE_MOUSE_TIMEOUT = 200; - -var lastMouseMoveEvent = null; - -function mouseMoveEventBuffered(event) { - lastMouseMoveEvent = event; -} - -function mouseMove(event) { - if (mouseDown && !mouseHasMovedSincePress) { - var timeSincePressMicro = Date.now() - mousePressStartTime; - - var dX = mousePressStartPosition.x - event.x; - var dY = mousePressStartPosition.y - event.y; - var sqDist = (dX * dX) + (dY * dY); - - // If less than CLICK_TIME_THRESHOLD has passed since the mouse click AND the mouse has moved - // less than CLICK_MOVE_DISTANCE_THRESHOLD distance, then don't register this as a mouse move - // yet. The goal is to provide mouse clicks that are more lenient to small movements. - if (timeSincePressMicro < CLICK_TIME_THRESHOLD && sqDist < CLICK_MOVE_DISTANCE_THRESHOLD) { - return; - } - mouseHasMovedSincePress = true; - } - - if (!isActive) { - return; - } - - // allow the selectionDisplay and cameraManager to handle the event first, if it doesn't handle it, then do our own thing - if (selectionDisplay.mouseMoveEvent(event) || propertyMenu.mouseMoveEvent(event) || cameraManager.mouseMoveEvent(event)) { - return; - } - - lastMousePosition = { - x: event.x, - y: event.y - }; -} - -function mouseReleaseEvent(event) { - mouseDown = false; - - if (lastMouseMoveEvent) { - mouseMove(lastMouseMoveEvent); - lastMouseMoveEvent = null; - } - if (propertyMenu.mouseReleaseEvent(event)) { - return true; - } - if (isActive && selectionManager.hasSelection()) { - tooltip.show(false); - } - if (mouseCapturedByTool) { - - return; - } - - cameraManager.mouseReleaseEvent(event); - - if (!mouseHasMovedSincePress) { - mouseClickEvent(event); - } -} - -function wasTabletOrEditHandleClicked(event) { - var rayPick = Camera.computePickRay(event.x, event.y); - var result = Overlays.findRayIntersection(rayPick, true); - if (result.intersects) { - var overlayID = result.overlayID; - var tabletIDs = getMainTabletIDs(); - if (tabletIDs.indexOf(overlayID) >= 0) { - return true; - } else if (selectionDisplay.isEditHandle(overlayID)) { - return true; - } - } - return false; -} - -function mouseClickEvent(event) { - var wantDebug = false; - var result, properties, tabletClicked; - if (isActive && event.isLeftButton) { - result = findClickedEntity(event); - var tabletOrEditHandleClicked = wasTabletOrEditHandleClicked(event); - if (tabletOrEditHandleClicked) { - return; - } - - if (result === null || result === undefined) { - if (!event.isShifted) { - selectionManager.clearSelections(this); - } - return; - } - toolBar.setActive(true); - var pickRay = result.pickRay; - var foundEntity = result.entityID; - if (HMD.tabletID && foundEntity === HMD.tabletID) { - return; - } - properties = Entities.getEntityProperties(foundEntity); - var halfDiagonal = Vec3.length(properties.dimensions) / 2.0; - - if (wantDebug) { - print("Checking properties: " + properties.id + " " + " - Half Diagonal:" + halfDiagonal); - } - // P P - Model - // /| A - Palm - // / | d B - unit vector toward tip - // / | X - base of the perpendicular line - // A---X----->B d - distance fom axis - // x x - distance from A - // - // |X-A| = (P-A).B - // X === A + ((P-A).B)B - // d = |P-X| - - var A = pickRay.origin; - var B = Vec3.normalize(pickRay.direction); - var P = properties.position; - - var x = Vec3.dot(Vec3.subtract(P, A), B); - - var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), properties.position)) * - 180 / Math.PI; - - var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) && - (allowSmallModels || angularSize > MIN_ANGULAR_SIZE); - - if (0 < x && sizeOK) { - selectedEntityID = foundEntity; - orientation = MyAvatar.orientation; - intersection = rayPlaneIntersection(pickRay, P, Quat.getForward(orientation)); - - if (!event.isShifted) { - selectionManager.setSelections([foundEntity], this); - } else { - selectionManager.addEntity(foundEntity, true, this); - } - selectionManager.saveProperties(); - - if (wantDebug) { - print("Model selected: " + foundEntity); - } - selectionDisplay.select(selectedEntityID, event); - - if (Menu.isOptionChecked(MENU_AUTO_FOCUS_ON_SELECT)) { - cameraManager.enable(); - cameraManager.focus(selectionManager.worldPosition, - selectionManager.worldDimensions, - Menu.isOptionChecked(MENU_EASE_ON_FOCUS)); - } - } - } else if (event.isRightButton) { - result = findClickedEntity(event); - if (result) { - if (SHOULD_SHOW_PROPERTY_MENU !== true) { - return; - } - properties = Entities.getEntityProperties(result.entityID); - if (properties.marketplaceID) { - propertyMenu.marketplaceID = properties.marketplaceID; - propertyMenu.updateMenuItemText(showMenuItem, "Show in Marketplace"); - } else { - propertyMenu.marketplaceID = null; - propertyMenu.updateMenuItemText(showMenuItem, "No marketplace info"); - } - propertyMenu.setPosition(event.x, event.y); - propertyMenu.show(); - } else { - propertyMenu.hide(); - } - } -} - -Controller.mousePressEvent.connect(mousePressEvent); -Controller.mouseMoveEvent.connect(mouseMoveEventBuffered); -Controller.mouseReleaseEvent.connect(mouseReleaseEvent); - - -// In order for editVoxels and editModels to play nice together, they each check to see if a "delete" menu item already -// exists. If it doesn't they add it. If it does they don't. They also only delete the menu item if they were the one that -// added it. -var modelMenuAddedDelete = false; -var originalLightsArePickable = Entities.getLightsArePickable(); - -function setupModelMenus() { - // adj our menuitems - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Undo", - shortcutKey: 'Ctrl+Z', - position: 0, - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Redo", - shortcutKey: 'Ctrl+Y', - position: 1, - }); - - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Entities", - isSeparator: true - }); - if (!Menu.menuItemExists("Edit", "Delete")) { - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Delete", - shortcutKeyEvent: { - text: "delete" - }, - afterItem: "Entities", - }); - modelMenuAddedDelete = true; - } - - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Parent Entity to Last", - afterItem: "Entities" - }); - - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Unparent Entity", - afterItem: "Parent Entity to Last" - }); - - Menu.addMenuItem({ - menuName: GRABBABLE_ENTITIES_MENU_CATEGORY, - menuItemName: MENU_CREATE_ENTITIES_GRABBABLE, - afterItem: "Unparent Entity", - isCheckable: true, - isChecked: Settings.getValue(SETTING_EDIT_PREFIX + MENU_CREATE_ENTITIES_GRABBABLE, true) - }); - - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: MENU_ALLOW_SELECTION_LARGE, - afterItem: MENU_CREATE_ENTITIES_GRABBABLE, - isCheckable: true, - isChecked: Settings.getValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_LARGE, true) - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: MENU_ALLOW_SELECTION_SMALL, - afterItem: MENU_ALLOW_SELECTION_LARGE, - isCheckable: true, - isChecked: Settings.getValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_SMALL, true) - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: MENU_ALLOW_SELECTION_LIGHTS, - afterItem: MENU_ALLOW_SELECTION_SMALL, - isCheckable: true, - isChecked: Settings.getValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_LIGHTS, false) - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Select All Entities In Box", - afterItem: "Allow Selecting of Lights" - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Select All Entities Touching Box", - afterItem: "Select All Entities In Box" - }); - - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Export Entities", - afterItem: "Entities" - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Import Entities", - afterItem: "Export Entities" - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Import Entities from URL", - afterItem: "Import Entities" - }); - - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: MENU_AUTO_FOCUS_ON_SELECT, - isCheckable: true, - isChecked: Settings.getValue(SETTING_AUTO_FOCUS_ON_SELECT) === "true" - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: MENU_EASE_ON_FOCUS, - afterItem: MENU_AUTO_FOCUS_ON_SELECT, - isCheckable: true, - isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) === "true" - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE, - afterItem: MENU_EASE_ON_FOCUS, - isCheckable: true, - isChecked: Settings.getValue(SETTING_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE) !== "false" - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: MENU_SHOW_ZONES_IN_EDIT_MODE, - afterItem: MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE, - isCheckable: true, - isChecked: Settings.getValue(SETTING_SHOW_ZONES_IN_EDIT_MODE) !== "false" - }); - - Entities.setLightsArePickable(false); -} - -setupModelMenus(); // do this when first running our script. - -function cleanupModelMenus() { - Menu.removeMenuItem("Edit", "Undo"); - Menu.removeMenuItem("Edit", "Redo"); - - Menu.removeSeparator("Edit", "Entities"); - if (modelMenuAddedDelete) { - // delete our menuitems - Menu.removeMenuItem("Edit", "Delete"); - } - - Menu.removeMenuItem("Edit", "Parent Entity to Last"); - Menu.removeMenuItem("Edit", "Unparent Entity"); - Menu.removeMenuItem("Edit", "Allow Selecting of Large Models"); - Menu.removeMenuItem("Edit", "Allow Selecting of Small Models"); - Menu.removeMenuItem("Edit", "Allow Selecting of Lights"); - Menu.removeMenuItem("Edit", "Select All Entities In Box"); - Menu.removeMenuItem("Edit", "Select All Entities Touching Box"); - - Menu.removeMenuItem("Edit", "Export Entities"); - Menu.removeMenuItem("Edit", "Import Entities"); - Menu.removeMenuItem("Edit", "Import Entities from URL"); - - Menu.removeMenuItem("Edit", MENU_AUTO_FOCUS_ON_SELECT); - Menu.removeMenuItem("Edit", MENU_EASE_ON_FOCUS); - Menu.removeMenuItem("Edit", MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE); - Menu.removeMenuItem("Edit", MENU_SHOW_ZONES_IN_EDIT_MODE); - Menu.removeMenuItem("Edit", MENU_CREATE_ENTITIES_GRABBABLE); -} - -Script.scriptEnding.connect(function () { - toolBar.setActive(false); - Settings.setValue(SETTING_AUTO_FOCUS_ON_SELECT, Menu.isOptionChecked(MENU_AUTO_FOCUS_ON_SELECT)); - Settings.setValue(SETTING_EASE_ON_FOCUS, Menu.isOptionChecked(MENU_EASE_ON_FOCUS)); - Settings.setValue(SETTING_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE, Menu.isOptionChecked(MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE)); - Settings.setValue(SETTING_SHOW_ZONES_IN_EDIT_MODE, Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE)); - - Settings.setValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_LARGE, Menu.isOptionChecked(MENU_ALLOW_SELECTION_LARGE)); - Settings.setValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_SMALL, Menu.isOptionChecked(MENU_ALLOW_SELECTION_SMALL)); - Settings.setValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_LIGHTS, Menu.isOptionChecked(MENU_ALLOW_SELECTION_LIGHTS)); - - - progressDialog.cleanup(); - cleanupModelMenus(); - tooltip.cleanup(); - selectionDisplay.cleanup(); - entityShapeVisualizer.cleanup(); - Entities.setLightsArePickable(originalLightsArePickable); - - Overlays.deleteOverlay(importingSVOImageOverlay); - Overlays.deleteOverlay(importingSVOTextOverlay); - - Controller.keyReleaseEvent.disconnect(keyReleaseEvent); - Controller.keyPressEvent.disconnect(keyPressEvent); - - Controller.mousePressEvent.disconnect(mousePressEvent); - Controller.mouseMoveEvent.disconnect(mouseMoveEventBuffered); - Controller.mouseReleaseEvent.disconnect(mouseReleaseEvent); - - Messages.messageReceived.disconnect(handleMessagesReceived); - Messages.unsubscribe("entityToolUpdates"); - createButton = null; -}); - -var lastOrientation = null; -var lastPosition = null; - -// Do some stuff regularly, like check for placement of various overlays -Script.update.connect(function (deltaTime) { - progressDialog.move(); - selectionDisplay.checkControllerMove(); - var dOrientation = Math.abs(Quat.dot(Camera.orientation, lastOrientation) - 1); - var dPosition = Vec3.distance(Camera.position, lastPosition); - if (dOrientation > 0.001 || dPosition > 0.001) { - propertyMenu.hide(); - lastOrientation = Camera.orientation; - lastPosition = Camera.position; - } - if (lastMouseMoveEvent) { - mouseMove(lastMouseMoveEvent); - lastMouseMoveEvent = null; - } -}); - -function insideBox(center, dimensions, point) { - return (Math.abs(point.x - center.x) <= (dimensions.x / 2.0)) && - (Math.abs(point.y - center.y) <= (dimensions.y / 2.0)) && - (Math.abs(point.z - center.z) <= (dimensions.z / 2.0)); -} - -function selectAllEntitiesInCurrentSelectionBox(keepIfTouching) { - if (selectionManager.hasSelection()) { - // Get all entities touching the bounding box of the current selection - var boundingBoxCorner = Vec3.subtract(selectionManager.worldPosition, - Vec3.multiply(selectionManager.worldDimensions, 0.5)); - var entities = Entities.findEntitiesInBox(boundingBoxCorner, selectionManager.worldDimensions); - - if (!keepIfTouching) { - var isValid; - if (selectionManager.localPosition === null || selectionManager.localPosition === undefined) { - isValid = function (position) { - return insideBox(selectionManager.worldPosition, selectionManager.worldDimensions, position); - }; - } else { - isValid = function (position) { - var localPosition = Vec3.multiplyQbyV(Quat.inverse(selectionManager.localRotation), - Vec3.subtract(position, - selectionManager.localPosition)); - return insideBox(Vec3.ZERO, selectionManager.localDimensions, localPosition); - }; - } - for (var i = 0; i < entities.length; ++i) { - var properties = Entities.getEntityProperties(entities[i]); - if (!isValid(properties.position)) { - entities.splice(i, 1); - --i; - } - } - } - selectionManager.setSelections(entities, this); - } -} - -function sortSelectedEntities(selected) { - var sortedEntities = selected.slice(); - var begin = 0; - while (begin < sortedEntities.length) { - var elementRemoved = false; - var next = begin + 1; - while (next < sortedEntities.length) { - var beginID = sortedEntities[begin]; - var nextID = sortedEntities[next]; - - if (Entities.isChildOfParent(beginID, nextID)) { - sortedEntities[begin] = nextID; - sortedEntities[next] = beginID; - sortedEntities.splice(next, 1); - elementRemoved = true; - break; - } else if (Entities.isChildOfParent(nextID, beginID)) { - sortedEntities.splice(next, 1); - elementRemoved = true; - break; - } - next++; - } - if (!elementRemoved) { - begin++; - } - } - return sortedEntities; -} - -function recursiveDelete(entities, childrenList, deletedIDs, entityHostType) { - var wantDebug = false; - var entitiesLength = entities.length; - var initialPropertySets = Entities.getMultipleEntityProperties(entities); - var entityHostTypes = Entities.getMultipleEntityProperties(entities, 'entityHostType'); - for (var i = 0; i < entitiesLength; ++i) { - var entityID = entities[i]; - - if (entityHostTypes[i].entityHostType !== entityHostType) { - if (wantDebug) { - console.log("Skipping deletion of entity " + entityID + " with conflicting entityHostType: " + - entityHostTypes[i].entityHostType + ", expected: " + entityHostType); - } - continue; - } - - var children = Entities.getChildrenIDs(entityID); - var grandchildrenList = []; - recursiveDelete(children, grandchildrenList, deletedIDs, entityHostType); - childrenList.push({ - entityID: entityID, - properties: initialPropertySets[i], - children: grandchildrenList - }); - deletedIDs.push(entityID); - Entities.deleteEntity(entityID); - } -} - -function unparentSelectedEntities() { - if (SelectionManager.hasSelection()) { - var selectedEntities = selectionManager.selections; - var parentCheck = false; - - if (selectedEntities.length < 1) { - Window.notifyEditError("You must have an entity selected in order to unparent it."); - return; - } - selectedEntities.forEach(function (id, index) { - var parentId = Entities.getEntityProperties(id, ["parentID"]).parentID; - if (parentId !== null && parentId.length > 0 && parentId !== Uuid.NULL) { - parentCheck = true; - } - Entities.editEntity(id, {parentID: null}); - return true; - }); - if (parentCheck) { - if (selectedEntities.length > 1) { - Window.notify("Entities unparented"); - } else { - Window.notify("Entity unparented"); - } - } else { - if (selectedEntities.length > 1) { - Window.notify("Selected Entities have no parents"); - } else { - Window.notify("Selected Entity does not have a parent"); - } - } - } else { - Window.notifyEditError("You have nothing selected to unparent"); - } -} -function parentSelectedEntities() { - if (SelectionManager.hasSelection()) { - var selectedEntities = selectionManager.selections; - if (selectedEntities.length <= 1) { - Window.notifyEditError("You must have multiple entities selected in order to parent them"); - return; - } - var parentCheck = false; - var lastEntityId = selectedEntities[selectedEntities.length - 1]; - selectedEntities.forEach(function (id, index) { - if (lastEntityId !== id) { - var parentId = Entities.getEntityProperties(id, ["parentID"]).parentID; - if (parentId !== lastEntityId) { - parentCheck = true; - } - Entities.editEntity(id, {parentID: lastEntityId}); - } - }); - - if (parentCheck) { - Window.notify("Entities parented"); - } else { - Window.notify("Entities are already parented to last"); - } - } else { - Window.notifyEditError("You have nothing selected to parent"); - } -} -function deleteSelectedEntities() { - if (SelectionManager.hasSelection()) { - var deletedIDs = []; - - SelectionManager.saveProperties(); - var savedProperties = []; - var newSortedSelection = sortSelectedEntities(selectionManager.selections); - var entityHostTypes = Entities.getMultipleEntityProperties(newSortedSelection, 'entityHostType'); - for (var i = 0; i < newSortedSelection.length; ++i) { - var entityID = newSortedSelection[i]; - var initialProperties = SelectionManager.savedProperties[entityID]; - if (initialProperties.locked || - (initialProperties.avatarEntity && initialProperties.owningAvatarID !== MyAvatar.sessionUUID)) { - continue; - } - var children = Entities.getChildrenIDs(entityID); - var childList = []; - recursiveDelete(children, childList, deletedIDs, entityHostTypes[i].entityHostType); - savedProperties.push({ - entityID: entityID, - properties: initialProperties, - children: childList - }); - deletedIDs.push(entityID); - Entities.deleteEntity(entityID); - } - - if (savedProperties.length > 0) { - SelectionManager.clearSelections(this); - pushCommandForSelections([], savedProperties); - entityListTool.deleteEntities(deletedIDs); - } - } -} - -function toggleSelectedEntitiesLocked() { - if (SelectionManager.hasSelection()) { - var locked = !Entities.getEntityProperties(SelectionManager.selections[0], ["locked"]).locked; - for (var i = 0; i < selectionManager.selections.length; i++) { - var entityID = SelectionManager.selections[i]; - Entities.editEntity(entityID, { - locked: locked - }); - } - entityListTool.sendUpdate(); - selectionManager._update(false, this); - } -} - -function toggleSelectedEntitiesVisible() { - if (SelectionManager.hasSelection()) { - var visible = !Entities.getEntityProperties(SelectionManager.selections[0], ["visible"]).visible; - for (var i = 0; i < selectionManager.selections.length; i++) { - var entityID = SelectionManager.selections[i]; - Entities.editEntity(entityID, { - visible: visible - }); - } - entityListTool.sendUpdate(); - selectionManager._update(false, this); - } -} - -function onFileSaveChanged(filename) { - Window.saveFileChanged.disconnect(onFileSaveChanged); - if (filename !== "") { - var success = Clipboard.exportEntities(filename, selectionManager.selections); - if (!success) { - Window.notifyEditError("Export failed."); - } - } -} - -function onFileOpenChanged(filename) { - // disconnect the event, otherwise the requests will stack up - try { - // Not all calls to onFileOpenChanged() connect an event. - Window.browseChanged.disconnect(onFileOpenChanged); - } catch (e) { - // Ignore. - } - - var importURL = null; - if (filename !== "") { - importURL = filename; - if (!/^(http|https):\/\//.test(filename)) { - importURL = "file:///" + importURL; - } - } - if (importURL) { - if (!isActive && (Entities.canRez() && Entities.canRezTmp() && Entities.canRezCertified() && Entities.canRezTmpCertified())) { - toolBar.toggle(); - } - importSVO(importURL); - } -} - -function onPromptTextChanged(prompt) { - Window.promptTextChanged.disconnect(onPromptTextChanged); - if (prompt !== "") { - if (!isActive && (Entities.canRez() && Entities.canRezTmp() && Entities.canRezCertified() && Entities.canRezTmpCertified())) { - toolBar.toggle(); - } - importSVO(prompt); - } -} - -function handleMenuEvent(menuItem) { - if (menuItem === "Allow Selecting of Small Models") { - allowSmallModels = Menu.isOptionChecked("Allow Selecting of Small Models"); - } else if (menuItem === "Allow Selecting of Large Models") { - allowLargeModels = Menu.isOptionChecked("Allow Selecting of Large Models"); - } else if (menuItem === "Allow Selecting of Lights") { - Entities.setLightsArePickable(Menu.isOptionChecked("Allow Selecting of Lights")); - } else if (menuItem === "Delete") { - deleteSelectedEntities(); - } else if (menuItem === "Undo") { - undoHistory.undo(); - } else if (menuItem === "Redo") { - undoHistory.redo(); - } else if (menuItem === "Parent Entity to Last") { - parentSelectedEntities(); - } else if (menuItem === "Unparent Entity") { - unparentSelectedEntities(); - } else if (menuItem === "Export Entities") { - if (!selectionManager.hasSelection()) { - Window.notifyEditError("No entities have been selected."); - } else { - Window.saveFileChanged.connect(onFileSaveChanged); - Window.saveAsync("Select Where to Save", "", "*.json"); - } - } else if (menuItem === "Import Entities" || menuItem === "Import Entities from URL") { - if (menuItem === "Import Entities") { - Window.browseChanged.connect(onFileOpenChanged); - Window.browseAsync("Select Model to Import", "", "*.json"); - } else { - Window.promptTextChanged.connect(onPromptTextChanged); - Window.promptAsync("URL of SVO to import", ""); - } - } else if (menuItem === "Select All Entities In Box") { - selectAllEntitiesInCurrentSelectionBox(false); - } else if (menuItem === "Select All Entities Touching Box") { - selectAllEntitiesInCurrentSelectionBox(true); - } else if (menuItem === MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE) { - entityIconOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE)); - } else if (menuItem === MENU_SHOW_ZONES_IN_EDIT_MODE) { - Entities.setDrawZoneBoundaries(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE)); - } else if (menuItem === MENU_CREATE_ENTITIES_GRABBABLE) { - Settings.setValue(SETTING_EDIT_PREFIX + menuItem, Menu.isOptionChecked(menuItem)); - } - tooltip.show(false); -} - -var HALF_TREE_SCALE = 16384; - -function getPositionToCreateEntity(extra) { - var CREATE_DISTANCE = 2; - var position; - var delta = extra !== undefined ? extra : 0; - if (Camera.mode === "entity" || Camera.mode === "independent") { - position = Vec3.sum(Camera.position, Vec3.multiply(Quat.getForward(Camera.orientation), CREATE_DISTANCE + delta)); - } else { - position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getForward(MyAvatar.orientation), CREATE_DISTANCE + delta)); - } - - if (position.x > HALF_TREE_SCALE || position.y > HALF_TREE_SCALE || position.z > HALF_TREE_SCALE) { - return null; - } - return position; -} - -function importSVO(importURL) { - if (!Entities.canRez() && !Entities.canRezTmp() && - !Entities.canRezCertified() && !Entities.canRezTmpCertified()) { - Window.notifyEditError(INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG); - return; - } - - Overlays.editOverlay(importingSVOTextOverlay, { - visible: true - }); - Overlays.editOverlay(importingSVOImageOverlay, { - visible: true - }); - - var success = Clipboard.importEntities(importURL); - - if (success) { - var VERY_LARGE = 10000; - var isLargeImport = Clipboard.getClipboardContentsLargestDimension() >= VERY_LARGE; - var position = Vec3.ZERO; - if (!isLargeImport) { - position = getPositionToCreateEntity(Clipboard.getClipboardContentsLargestDimension() / 2); - } - if (position !== null && position !== undefined) { - var pastedEntityIDs = Clipboard.pasteEntities(position); - if (!isLargeImport) { - // The first entity in Clipboard gets the specified position with the rest being relative to it. Therefore, move - // entities after they're imported so that they're all the correct distance in front of and with geometric mean - // centered on the avatar/camera direction. - var deltaPosition = Vec3.ZERO; - var entityPositions = []; - var entityParentIDs = []; - - var propType = Entities.getEntityProperties(pastedEntityIDs[0], ["type"]).type; - var NO_ADJUST_ENTITY_TYPES = ["Zone", "Light", "ParticleEffect"]; - if (NO_ADJUST_ENTITY_TYPES.indexOf(propType) === -1) { - var targetDirection; - if (Camera.mode === "entity" || Camera.mode === "independent") { - targetDirection = Camera.orientation; - } else { - targetDirection = MyAvatar.orientation; - } - targetDirection = Vec3.multiplyQbyV(targetDirection, Vec3.UNIT_Z); - - var targetPosition = getPositionToCreateEntity(); - var deltaParallel = HALF_TREE_SCALE; // Distance to move entities parallel to targetDirection. - var deltaPerpendicular = Vec3.ZERO; // Distance to move entities perpendicular to targetDirection. - for (var i = 0, length = pastedEntityIDs.length; i < length; i++) { - var curLoopEntityProps = Entities.getEntityProperties(pastedEntityIDs[i], ["position", "dimensions", - "registrationPoint", "rotation", "parentID"]); - var adjustedPosition = adjustPositionPerBoundingBox(targetPosition, targetDirection, - curLoopEntityProps.registrationPoint, curLoopEntityProps.dimensions, curLoopEntityProps.rotation); - var delta = Vec3.subtract(adjustedPosition, curLoopEntityProps.position); - var distance = Vec3.dot(delta, targetDirection); - deltaParallel = Math.min(distance, deltaParallel); - deltaPerpendicular = Vec3.sum(Vec3.subtract(delta, Vec3.multiply(distance, targetDirection)), - deltaPerpendicular); - entityPositions[i] = curLoopEntityProps.position; - entityParentIDs[i] = curLoopEntityProps.parentID; - } - deltaPerpendicular = Vec3.multiply(1 / pastedEntityIDs.length, deltaPerpendicular); - deltaPosition = Vec3.sum(Vec3.multiply(deltaParallel, targetDirection), deltaPerpendicular); - } - - if (grid.getSnapToGrid()) { - var firstEntityProps = Entities.getEntityProperties(pastedEntityIDs[0], ["position", "dimensions", - "registrationPoint"]); - var positionPreSnap = Vec3.sum(deltaPosition, firstEntityProps.position); - position = grid.snapToSurface(grid.snapToGrid(positionPreSnap, false, firstEntityProps.dimensions, - firstEntityProps.registrationPoint), firstEntityProps.dimensions, firstEntityProps.registrationPoint); - deltaPosition = Vec3.subtract(position, firstEntityProps.position); - } - - if (!Vec3.equal(deltaPosition, Vec3.ZERO)) { - for (var editEntityIndex = 0, numEntities = pastedEntityIDs.length; editEntityIndex < numEntities; editEntityIndex++) { - if (Uuid.isNull(entityParentIDs[editEntityIndex])) { - Entities.editEntity(pastedEntityIDs[editEntityIndex], { - position: Vec3.sum(deltaPosition, entityPositions[editEntityIndex]) - }); - } - } - } - } - - if (isActive) { - selectionManager.setSelections(pastedEntityIDs, this); - } - } else { - Window.notifyEditError("Can't import entities: entities would be out of bounds."); - } - } else { - Window.notifyEditError("There was an error importing the entity file."); - } - - Overlays.editOverlay(importingSVOTextOverlay, { - visible: false - }); - Overlays.editOverlay(importingSVOImageOverlay, { - visible: false - }); -} -Window.svoImportRequested.connect(importSVO); - -Menu.menuItemEvent.connect(handleMenuEvent); - -var keyPressEvent = function (event) { - if (isActive) { - cameraManager.keyPressEvent(event); - } -}; -var keyReleaseEvent = function (event) { - if (isActive) { - cameraManager.keyReleaseEvent(event); - } -}; -Controller.keyReleaseEvent.connect(keyReleaseEvent); -Controller.keyPressEvent.connect(keyPressEvent); - -function deleteKey(value) { - if (value === 0) { // on release - deleteSelectedEntities(); - } -} -function deselectKey(value) { - if (value === 0) { // on release - selectionManager.clearSelections(this); - } -} -function toggleKey(value) { - if (value === 0) { // on release - selectionDisplay.toggleSpaceMode(); - } -} -function focusKey(value) { - if (value === 0) { // on release - cameraManager.enable(); - if (selectionManager.hasSelection()) { - cameraManager.focus(selectionManager.worldPosition, selectionManager.worldDimensions, - Menu.isOptionChecked(MENU_EASE_ON_FOCUS)); - } - } -} -function gridKey(value) { - if (value === 0) { // on release - if (selectionManager.hasSelection()) { - grid.moveToSelection(); - } - } -} -function recursiveAdd(newParentID, parentData) { - if (parentData.children !== undefined) { - var children = parentData.children; - for (var i = 0; i < children.length; i++) { - var childProperties = children[i].properties; - childProperties.parentID = newParentID; - var newChildID = Entities.addEntity(childProperties); - recursiveAdd(newChildID, children[i]); - } - } -} - -var UndoHistory = function(onUpdate) { - this.history = []; - // The current position is the index of the last executed action in the history array. - // - // -1 0 1 2 3 <- position - // A B C D <- actions in history - // - // If our lastExecutedIndex is 1, the last executed action is B. - // If we undo, we undo B (index 1). If we redo, we redo C (index 2). - this.lastExecutedIndex = -1; - this.enabled = true; - this.onUpdate = onUpdate; -}; - -UndoHistory.prototype.pushCommand = function(undoFn, undoArgs, redoFn, redoArgs) { - if (!this.enabled) { - return; - } - // Delete any history following the last executed action. - this.history.splice(this.lastExecutedIndex + 1); - this.history.push({ - undoFn: undoFn, - undoArgs: undoArgs, - redoFn: redoFn, - redoArgs: redoArgs - }); - this.lastExecutedIndex++; - - if (this.onUpdate) { - this.onUpdate(); - } -}; -UndoHistory.prototype.setEnabled = function(enabled) { - this.enabled = enabled; - if (this.onUpdate) { - this.onUpdate(); - } -}; -UndoHistory.prototype.canUndo = function() { - return this.enabled && this.lastExecutedIndex >= 0; -}; -UndoHistory.prototype.canRedo = function() { - return this.enabled && this.lastExecutedIndex < this.history.length - 1; -}; -UndoHistory.prototype.undo = function() { - if (!this.canUndo()) { - console.warn("Cannot undo action"); - return; - } - - var command = this.history[this.lastExecutedIndex]; - command.undoFn(command.undoArgs); - this.lastExecutedIndex--; - - if (this.onUpdate) { - this.onUpdate(); - } -}; -UndoHistory.prototype.redo = function() { - if (!this.canRedo()) { - console.warn("Cannot redo action"); - return; - } - - var command = this.history[this.lastExecutedIndex + 1]; - command.redoFn(command.redoArgs); - this.lastExecutedIndex++; - - if (this.onUpdate) { - this.onUpdate(); - } -}; - -function updateUndoRedoMenuItems() { - Menu.setMenuEnabled("Edit > Undo", undoHistory.canUndo()); - Menu.setMenuEnabled("Edit > Redo", undoHistory.canRedo()); -} -var undoHistory = new UndoHistory(updateUndoRedoMenuItems); -updateUndoRedoMenuItems(); - -// When an entity has been deleted we need a way to "undo" this deletion. Because it's not currently -// possible to create an entity with a specific id, earlier undo commands to the deleted entity -// will fail if there isn't a way to find the new entity id. -var DELETED_ENTITY_MAP = {}; - -function applyEntityProperties(data) { - var editEntities = data.editEntities; - var createEntities = data.createEntities; - var deleteEntities = data.deleteEntities; - var selectedEntityIDs = []; - var selectEdits = createEntities.length === 0 || !data.selectCreated; - var i, entityID, entityProperties; - for (i = 0; i < createEntities.length; i++) { - entityID = createEntities[i].entityID; - entityProperties = createEntities[i].properties; - var newEntityID = Entities.addEntity(entityProperties); - recursiveAdd(newEntityID, createEntities[i]); - DELETED_ENTITY_MAP[entityID] = newEntityID; - if (data.selectCreated) { - selectedEntityIDs.push(newEntityID); - } - } - for (i = 0; i < deleteEntities.length; i++) { - entityID = deleteEntities[i].entityID; - if (DELETED_ENTITY_MAP[entityID] !== undefined) { - entityID = DELETED_ENTITY_MAP[entityID]; - } - Entities.deleteEntity(entityID); - var index = selectedEntityIDs.indexOf(entityID); - if (index >= 0) { - selectedEntityIDs.splice(index, 1); - } - } - for (i = 0; i < editEntities.length; i++) { - entityID = editEntities[i].entityID; - if (DELETED_ENTITY_MAP[entityID] !== undefined) { - entityID = DELETED_ENTITY_MAP[entityID]; - } - entityProperties = editEntities[i].properties; - if (entityProperties !== null) { - Entities.editEntity(entityID, entityProperties); - } - if (selectEdits) { - selectedEntityIDs.push(entityID); - } - } - - // We might be getting an undo while edit.js is disabled. If that is the case, don't set - // our selections, causing the edit widgets to display. - if (isActive) { - selectionManager.setSelections(selectedEntityIDs, this); - selectionManager.saveProperties(); - } -} - -// For currently selected entities, push a command to the UndoStack that uses the current entity properties for the -// redo command, and the saved properties for the undo command. Also, include create and delete entity data. -function pushCommandForSelections(createdEntityData, deletedEntityData, doNotSaveEditProperties) { - doNotSaveEditProperties = false; - var undoData = { - editEntities: [], - createEntities: deletedEntityData || [], - deleteEntities: createdEntityData || [], - selectCreated: true - }; - var redoData = { - editEntities: [], - createEntities: createdEntityData || [], - deleteEntities: deletedEntityData || [], - selectCreated: true - }; - for (var i = 0; i < SelectionManager.selections.length; i++) { - var entityID = SelectionManager.selections[i]; - var initialProperties = SelectionManager.savedProperties[entityID]; - var currentProperties = null; - if (!initialProperties) { - continue; - } - - if (doNotSaveEditProperties) { - initialProperties = null; - } else { - currentProperties = Entities.getEntityProperties(entityID); - } - - undoData.editEntities.push({ - entityID: entityID, - properties: initialProperties - }); - redoData.editEntities.push({ - entityID: entityID, - properties: currentProperties - }); - } - undoHistory.pushCommand(applyEntityProperties, undoData, applyEntityProperties, redoData); -} - -var ServerScriptStatusMonitor = function(entityID, statusCallback) { - var self = this; - - self.entityID = entityID; - self.active = true; - self.sendRequestTimerID = null; - - var onStatusReceived = function(success, isRunning, status, errorInfo) { - if (self.active) { - statusCallback({ - statusRetrieved: success, - isRunning: isRunning, - status: status, - errorInfo: errorInfo - }); - self.sendRequestTimerID = Script.setTimeout(function() { - if (self.active) { - Entities.getServerScriptStatus(entityID, onStatusReceived); - } - }, 1000); - } - }; - self.stop = function() { - self.active = false; - }; - - Entities.getServerScriptStatus(entityID, onStatusReceived); -}; - -var PropertiesTool = function (opts) { - var that = {}; - - var webView = null; - webView = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - webView.setVisible = function(value) {}; - - var visible = false; - - // This keeps track of the last entity ID that was selected. If multiple entities - // are selected or if no entity is selected this will be `null`. - var currentSelectedEntityID = null; - var statusMonitor = null; - var blockPropertyUpdates = false; - - that.setVisible = function (newVisible) { - visible = newVisible; - webView.setVisible(shouldUseEditTabletApp() && visible); - createToolsWindow.setVisible(!shouldUseEditTabletApp() && visible); - }; - - that.setVisible(false); - - function emitScriptEvent(data) { - var dataString = JSON.stringify(data); - webView.emitScriptEvent(dataString); - createToolsWindow.emitScriptEvent(dataString); - } - - function updateScriptStatus(info) { - info.type = "server_script_status"; - emitScriptEvent(info); - } - - function resetScriptStatus() { - updateScriptStatus({ - statusRetrieved: undefined, - isRunning: undefined, - status: "", - errorInfo: "" - }); - } - - that.setSpaceMode = function(spaceMode) { - emitScriptEvent({ - type: 'setSpaceMode', - spaceMode: spaceMode - }) - }; - - function updateSelections(selectionUpdated, caller) { - if (blockPropertyUpdates) { - return; - } - - var data = { - type: 'update', - spaceMode: selectionDisplay.getSpaceMode(), - isPropertiesToolUpdate: caller === this, - }; - - if (selectionUpdated) { - resetScriptStatus(); - - if (selectionManager.selections.length !== 1) { - if (statusMonitor !== null) { - statusMonitor.stop(); - statusMonitor = null; - } - currentSelectedEntityID = null; - } else if (currentSelectedEntityID !== selectionManager.selections[0]) { - if (statusMonitor !== null) { - statusMonitor.stop(); - } - var entityID = selectionManager.selections[0]; - currentSelectedEntityID = entityID; - statusMonitor = new ServerScriptStatusMonitor(entityID, updateScriptStatus); - } - } - - var selections = []; - for (var i = 0; i < selectionManager.selections.length; i++) { - var entity = {}; - entity.id = selectionManager.selections[i]; - entity.properties = Entities.getEntityProperties(selectionManager.selections[i]); - if (entity.properties.rotation !== undefined) { - entity.properties.rotation = Quat.safeEulerAngles(entity.properties.rotation); - } - if (entity.properties.localRotation !== undefined) { - entity.properties.localRotation = Quat.safeEulerAngles(entity.properties.localRotation); - } - if (entity.properties.emitOrientation !== undefined) { - entity.properties.emitOrientation = Quat.safeEulerAngles(entity.properties.emitOrientation); - } - if (entity.properties.keyLight !== undefined && entity.properties.keyLight.direction !== undefined) { - entity.properties.keyLight.direction = Vec3.toPolar(entity.properties.keyLight.direction); - entity.properties.keyLight.direction.z = 0.0; - } - selections.push(entity); - } - data.selections = selections; - - emitScriptEvent(data); - } - selectionManager.addEventListener(updateSelections, this); - - - var onWebEventReceived = function(data) { - try { - data = JSON.parse(data); - } catch(e) { - return; - } - var i, properties, dY, diff, newPosition; - if (data.type === "update") { - - if (data.properties || data.propertiesMap) { - var propertiesMap = data.propertiesMap; - if (propertiesMap === undefined) { - propertiesMap = [{ - entityIDs: data.ids, - properties: data.properties, - }]; - } - - var sendListUpdate = false; - propertiesMap.forEach(function(propertiesObject) { - var properties = propertiesObject.properties; - var updateEntityIDs = propertiesObject.entityIDs; - if (properties.dynamic === false) { - // this object is leaving dynamic, so we zero its velocities - properties.localVelocity = Vec3.ZERO; - properties.localAngularVelocity = Vec3.ZERO; - } - if (properties.rotation !== undefined) { - properties.rotation = Quat.fromVec3Degrees(properties.rotation); - } - if (properties.localRotation !== undefined) { - properties.localRotation = Quat.fromVec3Degrees(properties.localRotation); - } - if (properties.emitOrientation !== undefined) { - properties.emitOrientation = Quat.fromVec3Degrees(properties.emitOrientation); - } - if (properties.keyLight !== undefined && properties.keyLight.direction !== undefined) { - var currentKeyLightDirection = Vec3.toPolar(Entities.getEntityProperties(selectionManager.selections[0], ['keyLight.direction']).keyLight.direction); - if (properties.keyLight.direction.x === undefined) { - properties.keyLight.direction.x = currentKeyLightDirection.x; - } - if (properties.keyLight.direction.y === undefined) { - properties.keyLight.direction.y = currentKeyLightDirection.y; - } - properties.keyLight.direction = Vec3.fromPolar(properties.keyLight.direction.x, properties.keyLight.direction.y); - } - - updateEntityIDs.forEach(function (entityID) { - Entities.editEntity(entityID, properties); - }); - - if (properties.name !== undefined || properties.modelURL !== undefined || properties.materialURL !== undefined || - properties.visible !== undefined || properties.locked !== undefined) { - - sendListUpdate = true; - } - - }); - if (sendListUpdate) { - entityListTool.sendUpdate(); - } - } - - - if (data.onlyUpdateEntities) { - blockPropertyUpdates = true; - } else { - pushCommandForSelections(); - SelectionManager.saveProperties(); - } - selectionManager._update(false, this); - blockPropertyUpdates = false; - } else if (data.type === 'saveUserData' || data.type === 'saveMaterialData') { - data.ids.forEach(function(entityID) { - Entities.editEntity(entityID, data.properties); - }); - } else if (data.type === "showMarketplace") { - showMarketplace(); - } else if (data.type === "action") { - if (data.action === "moveSelectionToGrid") { - if (selectionManager.hasSelection()) { - selectionManager.saveProperties(); - dY = grid.getOrigin().y - (selectionManager.worldPosition.y - selectionManager.worldDimensions.y / 2); - diff = { - x: 0, - y: dY, - z: 0 - }; - for (i = 0; i < selectionManager.selections.length; i++) { - properties = selectionManager.savedProperties[selectionManager.selections[i]]; - newPosition = Vec3.sum(properties.position, diff); - Entities.editEntity(selectionManager.selections[i], { - position: newPosition - }); - } - pushCommandForSelections(); - selectionManager._update(false, this); - } - } else if (data.action === "moveAllToGrid") { - if (selectionManager.hasSelection()) { - selectionManager.saveProperties(); - for (i = 0; i < selectionManager.selections.length; i++) { - properties = selectionManager.savedProperties[selectionManager.selections[i]]; - var bottomY = properties.boundingBox.center.y - properties.boundingBox.dimensions.y / 2; - dY = grid.getOrigin().y - bottomY; - diff = { - x: 0, - y: dY, - z: 0 - }; - newPosition = Vec3.sum(properties.position, diff); - Entities.editEntity(selectionManager.selections[i], { - position: newPosition - }); - } - pushCommandForSelections(); - selectionManager._update(false, this); - } - } else if (data.action === "resetToNaturalDimensions") { - if (selectionManager.hasSelection()) { - selectionManager.saveProperties(); - for (i = 0; i < selectionManager.selections.length; i++) { - properties = selectionManager.savedProperties[selectionManager.selections[i]]; - var naturalDimensions = properties.naturalDimensions; - - // If any of the natural dimensions are not 0, resize - if (properties.type === "Model" && naturalDimensions.x === 0 && naturalDimensions.y === 0 && - naturalDimensions.z === 0) { - Window.notifyEditError("Cannot reset entity to its natural dimensions: Model URL" + - " is invalid or the model has not yet been loaded."); - } else { - Entities.editEntity(selectionManager.selections[i], { - dimensions: properties.naturalDimensions - }); - } - } - pushCommandForSelections(); - selectionManager._update(false, this); - } - } else if (data.action === "previewCamera") { - if (selectionManager.hasSelection()) { - Camera.mode = "entity"; - Camera.cameraEntity = selectionManager.selections[0]; - } - } else if (data.action === "rescaleDimensions") { - var multiplier = data.percentage / 100.0; - if (selectionManager.hasSelection()) { - selectionManager.saveProperties(); - for (i = 0; i < selectionManager.selections.length; i++) { - properties = selectionManager.savedProperties[selectionManager.selections[i]]; - Entities.editEntity(selectionManager.selections[i], { - dimensions: Vec3.multiply(multiplier, properties.dimensions) - }); - } - pushCommandForSelections(); - selectionManager._update(false, this); - } - } else if (data.action === "reloadClientScripts") { - if (selectionManager.hasSelection()) { - var timestamp = Date.now(); - for (i = 0; i < selectionManager.selections.length; i++) { - Entities.editEntity(selectionManager.selections[i], { - scriptTimestamp: timestamp - }); - } - } - } else if (data.action === "reloadServerScripts") { - if (selectionManager.hasSelection()) { - for (i = 0; i < selectionManager.selections.length; i++) { - Entities.reloadServerScripts(selectionManager.selections[i]); - } - } - } - } else if (data.type === "propertiesPageReady") { - updateSelections(true); - } else if (data.type === "tooltipsRequest") { - emitScriptEvent({ - type: 'tooltipsReply', - tooltips: Script.require('./assets/data/createAppTooltips.json'), - hmdActive: HMD.active, - }); - } else if (data.type === "propertyRangeRequest") { - var propertyRanges = {}; - data.properties.forEach(function (property) { - propertyRanges[property] = Entities.getPropertyInfo(property); - }); - emitScriptEvent({ - type: 'propertyRangeReply', - propertyRanges: propertyRanges, - }); - } else if (data.type === "materialTargetRequest") { - var parentModelData; - var properties = Entities.getEntityProperties(data.entityID, ["type", "parentID"]); - if (properties.type === "Material" && properties.parentID !== Uuid.NULL) { - var parentType = Entities.getEntityProperties(properties.parentID, ["type"]).type; - if (parentType === "Model" || Entities.getNestableType(properties.parentID) === "avatar") { - parentModelData = Graphics.getModel(properties.parentID); - } else if (parentType === "Shape" || parentType === "Box" || parentType === "Sphere") { - parentModelData = {}; - parentModelData.numMeshes = 1; - parentModelData.materialNames = []; - } - } - emitScriptEvent({ - type: 'materialTargetReply', - entityID: data.entityID, - materialTargetData: parentModelData, - }); - } - }; - - HMD.displayModeChanged.connect(function() { - emitScriptEvent({ - type: 'hmdActiveChanged', - hmdActive: HMD.active, - }); - }); - - createToolsWindow.webEventReceived.addListener(this, onWebEventReceived); - - webView.webEventReceived.connect(this, onWebEventReceived); - - return that; -}; - - -var PopupMenu = function () { - var self = this; - - var MENU_ITEM_HEIGHT = 21; - var MENU_ITEM_SPACING = 1; - var TEXT_MARGIN = 7; - - var overlays = []; - var overlayInfo = {}; - - var visible = false; - - var upColor = { - red: 0, - green: 0, - blue: 0 - }; - var downColor = { - red: 192, - green: 192, - blue: 192 - }; - var overColor = { - red: 128, - green: 128, - blue: 128 - }; - - self.onSelectMenuItem = function () {}; - - self.addMenuItem = function (name) { - var id = Overlays.addOverlay("text", { - text: name, - backgroundAlpha: 1.0, - backgroundColor: upColor, - topMargin: TEXT_MARGIN, - leftMargin: TEXT_MARGIN, - width: 210, - height: MENU_ITEM_HEIGHT, - font: { - size: 12 - }, - visible: false - }); - overlays.push(id); - overlayInfo[id] = { - name: name - }; - return id; - }; - - self.updateMenuItemText = function (id, newText) { - Overlays.editOverlay(id, { - text: newText - }); - }; - - self.setPosition = function (x, y) { - for (var key in overlayInfo) { - Overlays.editOverlay(key, { - x: x, - y: y - }); - y += MENU_ITEM_HEIGHT + MENU_ITEM_SPACING; - } - }; - - self.onSelected = function () {}; - - var pressingOverlay = null; - var hoveringOverlay = null; - - self.mousePressEvent = function (event) { - if (event.isLeftButton) { - var overlay = Overlays.getOverlayAtPoint({ - x: event.x, - y: event.y - }); - if (overlay in overlayInfo) { - pressingOverlay = overlay; - Overlays.editOverlay(pressingOverlay, { - backgroundColor: downColor - }); - } else { - self.hide(); - } - return false; - } - }; - self.mouseMoveEvent = function (event) { - if (visible) { - var overlay = Overlays.getOverlayAtPoint({ - x: event.x, - y: event.y - }); - if (!pressingOverlay) { - if (hoveringOverlay !== null && overlay !== hoveringOverlay) { - Overlays.editOverlay(hoveringOverlay, { - backgroundColor: upColor - }); - hoveringOverlay = null; - } - if (overlay !== hoveringOverlay && overlay in overlayInfo) { - Overlays.editOverlay(overlay, { - backgroundColor: overColor - }); - hoveringOverlay = overlay; - } - } - } - return false; - }; - self.mouseReleaseEvent = function (event) { - var overlay = Overlays.getOverlayAtPoint({ - x: event.x, - y: event.y - }); - if (pressingOverlay !== null && pressingOverlay !== undefined) { - if (overlay === pressingOverlay) { - self.onSelectMenuItem(overlayInfo[overlay].name); - } - Overlays.editOverlay(pressingOverlay, { - backgroundColor: upColor - }); - pressingOverlay = null; - self.hide(); - } - }; - - self.setVisible = function (newVisible) { - if (newVisible !== visible) { - visible = newVisible; - for (var key in overlayInfo) { - Overlays.editOverlay(key, { - visible: newVisible - }); - } - } - }; - self.show = function () { - self.setVisible(true); - }; - self.hide = function () { - self.setVisible(false); - }; - - function cleanup() { - ContextOverlay.enabled = true; - for (var i = 0; i < overlays.length; i++) { - Overlays.deleteOverlay(overlays[i]); - } - Controller.mousePressEvent.disconnect(self.mousePressEvent); - Controller.mouseMoveEvent.disconnect(self.mouseMoveEvent); - Controller.mouseReleaseEvent.disconnect(self.mouseReleaseEvent); - - Entities.canRezChanged.disconnect(checkEditPermissionsAndUpdate); - Entities.canRezTmpChanged.disconnect(checkEditPermissionsAndUpdate); - Entities.canRezCertifiedChanged.disconnect(checkEditPermissionsAndUpdate); - Entities.canRezTmpCertifiedChanged.disconnect(checkEditPermissionsAndUpdate); - } - - Controller.mousePressEvent.connect(self.mousePressEvent); - Controller.mouseMoveEvent.connect(self.mouseMoveEvent); - Controller.mouseReleaseEvent.connect(self.mouseReleaseEvent); - Script.scriptEnding.connect(cleanup); - - return this; -}; - -function whenPressed(fn) { - return function(value) { - if (value > 0) { - fn(); - } - }; -} - -function whenReleased(fn) { - return function(value) { - if (value === 0) { - fn(); - } - }; -} - -var isOnMacPlatform = Controller.getValue(Controller.Hardware.Application.PlatformMac); - -var mapping = Controller.newMapping(CONTROLLER_MAPPING_NAME); -if (isOnMacPlatform) { - mapping.from([Controller.Hardware.Keyboard.Backspace]).to(deleteKey); -} else { - mapping.from([Controller.Hardware.Keyboard.Delete]).to(deleteKey); -} -mapping.from([Controller.Hardware.Keyboard.T]).to(toggleKey); -mapping.from([Controller.Hardware.Keyboard.F]).to(focusKey); -mapping.from([Controller.Hardware.Keyboard.G]).to(gridKey); -mapping.from([Controller.Hardware.Keyboard.X]) - .when([Controller.Hardware.Keyboard.Control]) - .to(whenReleased(function() { selectionManager.cutSelectedEntities() })); -mapping.from([Controller.Hardware.Keyboard.C]) - .when([Controller.Hardware.Keyboard.Control]) - .to(whenReleased(function() { selectionManager.copySelectedEntities() })); -mapping.from([Controller.Hardware.Keyboard.V]) - .when([Controller.Hardware.Keyboard.Control]) - .to(whenReleased(function() { selectionManager.pasteEntities() })); -mapping.from([Controller.Hardware.Keyboard.D]) - .when([Controller.Hardware.Keyboard.Control]) - .to(whenReleased(function() { selectionManager.duplicateSelection() })); - -// Bind undo to ctrl-shift-z to maintain backwards-compatibility -mapping.from([Controller.Hardware.Keyboard.Z]) - .when([Controller.Hardware.Keyboard.Control, Controller.Hardware.Keyboard.Shift]) - .to(whenPressed(function() { undoHistory.redo() })); - - -mapping.from([Controller.Hardware.Keyboard.P]) - .when([Controller.Hardware.Keyboard.Control, Controller.Hardware.Keyboard.Shift]) - .to(whenReleased(function() { unparentSelectedEntities(); })); - -mapping.from([Controller.Hardware.Keyboard.P]) - .when([Controller.Hardware.Keyboard.Control, !Controller.Hardware.Keyboard.Shift]) - .to(whenReleased(function() { parentSelectedEntities(); })); - -keyUpEventFromUIWindow = function(keyUpEvent) { - var WANT_DEBUG_MISSING_SHORTCUTS = false; - - var pressedValue = 0.0; - - if ((!isOnMacPlatform && keyUpEvent.keyCodeString === "Delete") - || (isOnMacPlatform && keyUpEvent.keyCodeString === "Backspace")) { - - deleteKey(pressedValue); - } else if (keyUpEvent.keyCodeString === "T") { - toggleKey(pressedValue); - } else if (keyUpEvent.keyCodeString === "F") { - focusKey(pressedValue); - } else if (keyUpEvent.keyCodeString === "G") { - gridKey(pressedValue); - } else if (keyUpEvent.controlKey && keyUpEvent.keyCodeString === "X") { - selectionManager.cutSelectedEntities(); - } else if (keyUpEvent.controlKey && keyUpEvent.keyCodeString === "C") { - selectionManager.copySelectedEntities(); - } else if (keyUpEvent.controlKey && keyUpEvent.keyCodeString === "V") { - selectionManager.pasteEntities(); - } else if (keyUpEvent.controlKey && keyUpEvent.keyCodeString === "D") { - selectionManager.duplicateSelection(); - } else if (!isOnMacPlatform && keyUpEvent.controlKey && !keyUpEvent.shiftKey && keyUpEvent.keyCodeString === "Z") { - undoHistory.undo(); // undo is only handled via handleMenuItem on Mac - } else if (keyUpEvent.controlKey && !keyUpEvent.shiftKey && keyUpEvent.keyCodeString === "P") { - parentSelectedEntities(); - } else if (keyUpEvent.controlKey && keyUpEvent.shiftKey && keyUpEvent.keyCodeString === "P") { - unparentSelectedEntities(); - } else if (!isOnMacPlatform && - ((keyUpEvent.controlKey && keyUpEvent.shiftKey && keyUpEvent.keyCodeString === "Z") || - (keyUpEvent.controlKey && keyUpEvent.keyCodeString === "Y"))) { - undoHistory.redo(); // redo is only handled via handleMenuItem on Mac - } else if (WANT_DEBUG_MISSING_SHORTCUTS) { - console.warn("unhandled key event: " + JSON.stringify(keyUpEvent)) - } -}; - -var propertyMenu = new PopupMenu(); - -propertyMenu.onSelectMenuItem = function (name) { - - if (propertyMenu.marketplaceID) { - showMarketplace(propertyMenu.marketplaceID); - } -}; - -var showMenuItem = propertyMenu.addMenuItem("Show in Marketplace"); - -var propertiesTool = new PropertiesTool(); - -selectionDisplay.onSpaceModeChange = function(spaceMode) { - entityListTool.setSpaceMode(spaceMode); - propertiesTool.setSpaceMode(spaceMode); -}; - -}()); // END LOCAL_SCOPE diff --git a/scripts/simplifiedUI/system/emote.js b/scripts/simplifiedUI/system/emote.js deleted file mode 100644 index 6dfd1ae1ef..0000000000 --- a/scripts/simplifiedUI/system/emote.js +++ /dev/null @@ -1,179 +0,0 @@ -"use strict"; - -// -// emote.js -// scripts/system/ -// -// Created by Brad Hefta-Gaub on 7 Jan 2018 -// Copyright 2018 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 -// -/* globals Script, Tablet */ -/* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ - -(function() { // BEGIN LOCAL_SCOPE - - -var EMOTE_ANIMATIONS = - ['Crying', 'Surprised', 'Dancing', 'Cheering', 'Waving', 'Fall', 'Pointing', 'Clapping', 'Sit1', 'Sit2', 'Sit3', 'Love']; -var ANIMATIONS = Array(); - -var eventMappingName = "io.highfidelity.away"; // restoreAnimation on hand controller button events, too -var eventMapping = Controller.newMapping(eventMappingName); - -EMOTE_ANIMATIONS.forEach(function (name) { - var animationURL = Script.resolvePath("assets/animations/" + name + ".fbx"); - var resource = AnimationCache.prefetch(animationURL); - var animation = AnimationCache.getAnimation(animationURL); - ANIMATIONS[name] = { url: animationURL, animation: animation, resource: resource}; -}); - - -var EMOTE_APP_BASE = "html/EmoteApp.html"; -var EMOTE_APP_URL = Script.resolvePath(EMOTE_APP_BASE); -var EMOTE_LABEL = "EMOTE"; -var EMOTE_APP_SORT_ORDER = 12; -var FPS = 60; -var MSEC_PER_SEC = 1000; -var FINISHED = 3; // see ScriptableResource::State - -var onEmoteScreen = false; -var button; -var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); -var activeTimer = false; // Used to cancel active timer if a user plays an animation while another animation is playing -var activeEmote = false; // To keep track of the currently playing emote - -button = tablet.addButton({ - icon: "icons/tablet-icons/emote-i.svg", - activeIcon: "icons/tablet-icons/emote-a.svg", - text: EMOTE_LABEL, - sortOrder: EMOTE_APP_SORT_ORDER -}); - -function onClicked() { - if (onEmoteScreen) { - tablet.gotoHomeScreen(); - } else { - onEmoteScreen = true; - tablet.gotoWebScreen(EMOTE_APP_URL); - } -} - -function onScreenChanged(type, url) { - onEmoteScreen = type === "Web" && (url.indexOf(EMOTE_APP_BASE) === url.length - EMOTE_APP_BASE.length); - button.editProperties({ isActive: onEmoteScreen }); -} - -// Handle the events we're receiving from the web UI -function onWebEventReceived(event) { - - // Converts the event to a JavasScript Object - if (typeof event === "string") { - event = JSON.parse(event); - } - - if (event.type === "click") { - - // Allow for a random sitting animation when a user selects sit - var randSit = Math.floor(Math.random() * 3) + 1; - - var emoteName = event.data; - - if (emoteName === "Sit"){ - emoteName = event.data + randSit; // Sit1, Sit2, Sit3 - } - - if (ANIMATIONS[emoteName].resource.state === FINISHED) { - - if (activeTimer !== false) { - Script.clearTimeout(activeTimer); - } - - // If the activeEmote is different from the chosen emote, then play the new emote - // This is a second click on the same emote as the activeEmote, and we will just stop it - if (activeEmote !== emoteName) { - activeEmote = emoteName; - - - // Sit is the only animation currently that plays and then ends at the last frame - if (emoteName.match(/^Sit.*$/)) { - - // If user provides input during a sit, the avatar animation state should be restored - Controller.keyPressEvent.connect(restoreAnimation); - Controller.enableMapping(eventMappingName); - MyAvatar.overrideAnimation(ANIMATIONS[emoteName].url, FPS, false, 0, frameCount); - - } else { - - activeEmote = emoteName; - var frameCount = ANIMATIONS[emoteName].animation.frames.length; - MyAvatar.overrideAnimation(ANIMATIONS[emoteName].url, FPS, false, 0, frameCount); - - var timeOut = MSEC_PER_SEC * frameCount / FPS; - activeTimer = Script.setTimeout(function () { - MyAvatar.restoreAnimation(); - activeTimer = false; - activeEmote = false; - }, timeOut); - - } - - } else { - activeEmote = false; - MyAvatar.restoreAnimation(); - } - } - } -} - -// Restore the navigation animation states (idle, walk, run) -function restoreAnimation() { - MyAvatar.restoreAnimation(); - - // Make sure the input is disconnected after animations are restored so it doesn't affect any emotes other than sit - Controller.keyPressEvent.disconnect(restoreAnimation); - Controller.disableMapping(eventMappingName); -} - -// Note peek() so as to not interfere with other mappings. -eventMapping.from(Controller.Standard.LeftPrimaryThumb).peek().to(restoreAnimation); -eventMapping.from(Controller.Standard.RightPrimaryThumb).peek().to(restoreAnimation); -eventMapping.from(Controller.Standard.LeftSecondaryThumb).peek().to(restoreAnimation); -eventMapping.from(Controller.Standard.RightSecondaryThumb).peek().to(restoreAnimation); -eventMapping.from(Controller.Standard.LB).peek().to(restoreAnimation); -eventMapping.from(Controller.Standard.LS).peek().to(restoreAnimation); -eventMapping.from(Controller.Standard.RY).peek().to(restoreAnimation); -eventMapping.from(Controller.Standard.RX).peek().to(restoreAnimation); -eventMapping.from(Controller.Standard.LY).peek().to(restoreAnimation); -eventMapping.from(Controller.Standard.LX).peek().to(restoreAnimation); -eventMapping.from(Controller.Standard.LeftGrip).peek().to(restoreAnimation); -eventMapping.from(Controller.Standard.RB).peek().to(restoreAnimation); -eventMapping.from(Controller.Standard.RS).peek().to(restoreAnimation); -eventMapping.from(Controller.Standard.RightGrip).peek().to(restoreAnimation); -eventMapping.from(Controller.Standard.Back).peek().to(restoreAnimation); -eventMapping.from(Controller.Standard.Start).peek().to(restoreAnimation); - - -button.clicked.connect(onClicked); -tablet.screenChanged.connect(onScreenChanged); -tablet.webEventReceived.connect(onWebEventReceived); - -Script.scriptEnding.connect(function () { - if (onEmoteScreen) { - tablet.gotoHomeScreen(); - } - button.clicked.disconnect(onClicked); - tablet.screenChanged.disconnect(onScreenChanged); - if (tablet) { - tablet.removeButton(button); - } - if (activeTimer !== false) { - Script.clearTimeout(activeTimer); - MyAvatar.restoreAnimation(); - } -}); - - -}()); // END LOCAL_SCOPE diff --git a/scripts/simplifiedUI/system/fingerPaint.js b/scripts/simplifiedUI/system/fingerPaint.js deleted file mode 100644 index 88245503e8..0000000000 --- a/scripts/simplifiedUI/system/fingerPaint.js +++ /dev/null @@ -1,465 +0,0 @@ -// -// fingerPaint.js -// -// Created by David Rowe on 15 Feb 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 -// - -(function () { - var tablet, - button, - BUTTON_NAME = "PAINT", - isFingerPainting = false, - shouldPointFingers = false, - leftHand = null, - rightHand = null, - leftBrush = null, - rightBrush = null, - CONTROLLER_MAPPING_NAME = "com.highfidelity.fingerPaint", - isTabletDisplayed = false, - HIFI_POINT_INDEX_MESSAGE_CHANNEL = "Hifi-Point-Index", - HIFI_GRAB_DISABLE_MESSAGE_CHANNEL = "Hifi-Grab-Disable", - HIFI_POINTER_DISABLE_MESSAGE_CHANNEL = "Hifi-Pointer-Disable"; - HOW_TO_EXIT_MESSAGE = "Press B on your controller to exit FingerPainting mode"; - - function paintBrush(name) { - // Paints in 3D. - var brushName = name, - STROKE_COLOR = { red: 250, green: 0, blue: 0 }, - ERASE_SEARCH_RADIUS = 0.1, // m - isDrawingLine = false, - entityID, - basePosition, - strokePoints, - strokeNormals, - strokeWidths, - timeOfLastPoint, - MIN_STROKE_LENGTH = 0.005, // m - MIN_STROKE_INTERVAL = 66, // ms - MAX_POINTS_PER_LINE = 70; // Hard-coded limit in PolyLineEntityItem.h. - - function strokeNormal() { - return Vec3.multiplyQbyV(Camera.getOrientation(), Vec3.UNIT_NEG_Z); - } - - function startLine(position, width) { - // Start drawing a polyline. - - if (isDrawingLine) { - print("ERROR: startLine() called when already drawing line"); - // Nevertheless, continue on and start a new line. - } - - basePosition = position; - - strokePoints = [Vec3.ZERO]; - strokeNormals = [strokeNormal()]; - strokeWidths = [width]; - timeOfLastPoint = Date.now(); - - entityID = Entities.addEntity({ - type: "PolyLine", - name: "fingerPainting", - color: STROKE_COLOR, - position: position, - linePoints: strokePoints, - normals: strokeNormals, - strokeWidths: strokeWidths, - dimensions: { x: 10, y: 10, z: 10 } - }); - - isDrawingLine = true; - } - - function drawLine(position, width) { - // Add a stroke to the polyline if stroke is a sufficient length. - var localPosition, - distanceToPrevious, - MAX_DISTANCE_TO_PREVIOUS = 1.0; - - if (!isDrawingLine) { - print("ERROR: drawLine() called when not drawing line"); - return; - } - - localPosition = Vec3.subtract(position, basePosition); - distanceToPrevious = Vec3.distance(localPosition, strokePoints[strokePoints.length - 1]); - - if (distanceToPrevious > MAX_DISTANCE_TO_PREVIOUS) { - // Ignore occasional spurious finger tip positions. - return; - } - - if (distanceToPrevious >= MIN_STROKE_LENGTH - && (Date.now() - timeOfLastPoint) >= MIN_STROKE_INTERVAL - && strokePoints.length < MAX_POINTS_PER_LINE) { - strokePoints.push(localPosition); - strokeNormals.push(strokeNormal()); - strokeWidths.push(width); - timeOfLastPoint = Date.now(); - - Entities.editEntity(entityID, { - linePoints: strokePoints, - normals: strokeNormals, - strokeWidths: strokeWidths - }); - } - } - - function finishLine(position, width) { - // Finish drawing polyline; delete if it has only 1 point. - - if (!isDrawingLine) { - print("ERROR: finishLine() called when not drawing line"); - return; - } - - if (strokePoints.length === 1) { - // Delete "empty" line. - Entities.deleteEntity(entityID); - } - - isDrawingLine = false; - } - - function cancelLine() { - // Cancel any line being drawn. - if (isDrawingLine) { - Entities.deleteEntity(entityID); - isDrawingLine = false; - } - } - - function eraseClosestLine(position) { - // Erase closest line that is within search radius of finger tip. - var entities, - entitiesLength, - properties, - i, - pointsLength, - j, - distance, - found = false, - foundID, - foundDistance = ERASE_SEARCH_RADIUS; - - // Find entities with bounding box within search radius. - entities = Entities.findEntities(position, ERASE_SEARCH_RADIUS); - - // Fine polyline entity with closest point within search radius. - for (i = 0, entitiesLength = entities.length; i < entitiesLength; i += 1) { - properties = Entities.getEntityProperties(entities[i], ["type", "position", "linePoints"]); - if (properties.type === "PolyLine") { - basePosition = properties.position; - for (j = 0, pointsLength = properties.linePoints.length; j < pointsLength; j += 1) { - distance = Vec3.distance(position, Vec3.sum(basePosition, properties.linePoints[j])); - if (distance <= foundDistance) { - found = true; - foundID = entities[i]; - foundDistance = distance; - } - } - } - } - - // Delete found entity. - if (found) { - Entities.deleteEntity(foundID); - } - } - - function tearDown() { - cancelLine(); - } - - return { - startLine: startLine, - drawLine: drawLine, - finishLine: finishLine, - cancelLine: cancelLine, - eraseClosestLine: eraseClosestLine, - tearDown: tearDown - }; - } - - function handController(name) { - // Translates controller data into application events. - var handName = name, - - triggerPressedCallback, - triggerPressingCallback, - triggerReleasedCallback, - gripPressedCallback, - - rawTriggerValue = 0.0, - triggerValue = 0.0, - isTriggerPressed = false, - TRIGGER_SMOOTH_RATIO = 0.1, - TRIGGER_OFF = 0.05, - TRIGGER_ON = 0.1, - TRIGGER_START_WIDTH_RAMP = 0.15, - TRIGGER_FINISH_WIDTH_RAMP = 1.0, - TRIGGER_RAMP_WIDTH = TRIGGER_FINISH_WIDTH_RAMP - TRIGGER_START_WIDTH_RAMP, - MIN_LINE_WIDTH = 0.005, - MAX_LINE_WIDTH = 0.03, - RAMP_LINE_WIDTH = MAX_LINE_WIDTH - MIN_LINE_WIDTH, - - rawGripValue = 0.0, - gripValue = 0.0, - isGripPressed = false, - GRIP_SMOOTH_RATIO = 0.1, - GRIP_OFF = 0.05, - GRIP_ON = 0.1; - - function onTriggerPress(value) { - // Controller values are only updated when they change so store latest for use in update. - rawTriggerValue = value; - } - - function updateTriggerPress(value) { - var wasTriggerPressed, - fingerTipPosition, - lineWidth; - - triggerValue = triggerValue * TRIGGER_SMOOTH_RATIO + rawTriggerValue * (1.0 - TRIGGER_SMOOTH_RATIO); - - wasTriggerPressed = isTriggerPressed; - if (isTriggerPressed) { - isTriggerPressed = triggerValue > TRIGGER_OFF; - } else { - isTriggerPressed = triggerValue > TRIGGER_ON; - } - - if (wasTriggerPressed || isTriggerPressed) { - fingerTipPosition = MyAvatar.getJointPosition(handName === "left" ? "LeftHandIndex4" : "RightHandIndex4"); - if (triggerValue < TRIGGER_START_WIDTH_RAMP) { - lineWidth = MIN_LINE_WIDTH; - } else { - lineWidth = MIN_LINE_WIDTH - + (triggerValue - TRIGGER_START_WIDTH_RAMP) / TRIGGER_RAMP_WIDTH * RAMP_LINE_WIDTH; - } - - if (!wasTriggerPressed && isTriggerPressed) { - triggerPressedCallback(fingerTipPosition, lineWidth); - } else if (wasTriggerPressed && isTriggerPressed) { - triggerPressingCallback(fingerTipPosition, lineWidth); - } else { - triggerReleasedCallback(fingerTipPosition, lineWidth); - } - } - } - - function onGripPress(value) { - // Controller values are only updated when they change so store latest for use in update. - rawGripValue = value; - } - - function updateGripPress() { - var fingerTipPosition; - - gripValue = gripValue * GRIP_SMOOTH_RATIO + rawGripValue * (1.0 - GRIP_SMOOTH_RATIO); - - if (isGripPressed) { - isGripPressed = gripValue > GRIP_OFF; - } else { - isGripPressed = gripValue > GRIP_ON; - if (isGripPressed) { - fingerTipPosition = MyAvatar.getJointPosition(handName === "left" ? "LeftHandIndex4" : "RightHandIndex4"); - gripPressedCallback(fingerTipPosition); - } - } - } - - function onUpdate() { - updateTriggerPress(); - updateGripPress(); - } - - function setUp(onTriggerPressed, onTriggerPressing, onTriggerReleased, onGripPressed) { - triggerPressedCallback = onTriggerPressed; - triggerPressingCallback = onTriggerPressing; - triggerReleasedCallback = onTriggerReleased; - gripPressedCallback = onGripPressed; - } - - function tearDown() { - // Nothing to do. - } - - return { - onTriggerPress: onTriggerPress, - onGripPress: onGripPress, - onUpdate: onUpdate, - setUp: setUp, - tearDown: tearDown - }; - } - - function updateHandFunctions() { - // Update other scripts' hand functions. - var enabled = !isFingerPainting || isTabletDisplayed; - - Messages.sendMessage(HIFI_GRAB_DISABLE_MESSAGE_CHANNEL, JSON.stringify({ - holdEnabled: enabled, - nearGrabEnabled: enabled, - farGrabEnabled: enabled - }), true); - Messages.sendMessage(HIFI_POINTER_DISABLE_MESSAGE_CHANNEL, JSON.stringify({ - pointerEnabled: enabled - }), true); - - var newShouldPointFingers = !enabled; - if (newShouldPointFingers !== shouldPointFingers) { - Messages.sendMessage(HIFI_POINT_INDEX_MESSAGE_CHANNEL, JSON.stringify({ - pointIndex: newShouldPointFingers - }), true); - shouldPointFingers = newShouldPointFingers; - } - } - - function howToExitTutorial() { - HMD.requestShowHandControllers(); - setControllerPartLayer('button_b', 'highlight'); - messageWindow = Window.alert(HOW_TO_EXIT_MESSAGE); - setControllerPartLayer('button_b', 'blank'); - HMD.requestHideHandControllers(); - Settings.setValue("FingerPaintTutorialComplete", true); - } - - function enableProcessing() { - // Connect controller API to handController objects. - leftHand = handController("left"); - rightHand = handController("right"); - var controllerMapping = Controller.newMapping(CONTROLLER_MAPPING_NAME); - controllerMapping.from(Controller.Standard.LT).to(leftHand.onTriggerPress); - controllerMapping.from(Controller.Standard.LeftGrip).to(leftHand.onGripPress); - controllerMapping.from(Controller.Standard.RT).to(rightHand.onTriggerPress); - controllerMapping.from(Controller.Standard.RightGrip).to(rightHand.onGripPress); - controllerMapping.from(Controller.Standard.B).to(onButtonClicked); - Controller.enableMapping(CONTROLLER_MAPPING_NAME); - - if (!Settings.getValue("FingerPaintTutorialComplete")) { - howToExitTutorial(); - } - - // Connect handController outputs to paintBrush objects. - leftBrush = paintBrush("left"); - leftHand.setUp(leftBrush.startLine, leftBrush.drawLine, leftBrush.finishLine, leftBrush.eraseClosestLine); - rightBrush = paintBrush("right"); - rightHand.setUp(rightBrush.startLine, rightBrush.drawLine, rightBrush.finishLine, rightBrush.eraseClosestLine); - - // Messages channels for enabling/disabling other scripts' functions. - Messages.subscribe(HIFI_POINT_INDEX_MESSAGE_CHANNEL); - Messages.subscribe(HIFI_GRAB_DISABLE_MESSAGE_CHANNEL); - Messages.subscribe(HIFI_POINTER_DISABLE_MESSAGE_CHANNEL); - - // Update hand controls. - Script.update.connect(leftHand.onUpdate); - Script.update.connect(rightHand.onUpdate); - } - - function disableProcessing() { - Script.update.disconnect(leftHand.onUpdate); - Script.update.disconnect(rightHand.onUpdate); - - Controller.disableMapping(CONTROLLER_MAPPING_NAME); - - leftBrush.tearDown(); - leftBrush = null; - leftHand.tearDown(); - leftHand = null; - - rightBrush.tearDown(); - rightBrush = null; - rightHand.tearDown(); - rightHand = null; - - Messages.unsubscribe(HIFI_POINT_INDEX_MESSAGE_CHANNEL); - Messages.unsubscribe(HIFI_GRAB_DISABLE_MESSAGE_CHANNEL); - Messages.unsubscribe(HIFI_POINTER_DISABLE_MESSAGE_CHANNEL); - } - - function onButtonClicked() { - var wasFingerPainting = isFingerPainting; - - isFingerPainting = !isFingerPainting; - button.editProperties({ isActive: isFingerPainting }); - - print("Finger painting: " + isFingerPainting ? "on" : "off"); - - if (wasFingerPainting) { - leftBrush.cancelLine(); - rightBrush.cancelLine(); - } - - if (isFingerPainting) { - enableProcessing(); - } - - updateHandFunctions(); - - if (!isFingerPainting) { - disableProcessing(); - } - } - - function onTabletScreenChanged(type, url) { - var TABLET_SCREEN_CLOSED = "Closed"; - - isTabletDisplayed = type !== TABLET_SCREEN_CLOSED; - updateHandFunctions(); - } - - function setUp() { - tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - if (!tablet) { - return; - } - - // Tablet button. - button = tablet.addButton({ - icon: "icons/tablet-icons/finger-paint-i.svg", - activeIcon: "icons/tablet-icons/finger-paint-a.svg", - text: BUTTON_NAME, - isActive: isFingerPainting - }); - button.clicked.connect(onButtonClicked); - - // Track whether tablet is displayed or not. - tablet.screenChanged.connect(onTabletScreenChanged); - } - - function tearDown() { - if (!tablet) { - return; - } - - if (isFingerPainting) { - isFingerPainting = false; - updateHandFunctions(); - disableProcessing(); - } - - tablet.screenChanged.disconnect(onTabletScreenChanged); - - button.clicked.disconnect(onButtonClicked); - tablet.removeButton(button); - } - - /** - * A controller is made up of parts, and each part can have multiple "layers," - * which are really just different texures. For example, the "trigger" part - * has "normal" and "highlight" layers. - */ - function setControllerPartLayer(part, layer) { - data = {}; - data[part] = layer; - Messages.sendLocalMessage('Controller-Set-Part-Layer', JSON.stringify(data)); - } - - setUp(); - Script.scriptEnding.connect(tearDown); -}()); diff --git a/scripts/simplifiedUI/system/firstPersonHMD.js b/scripts/simplifiedUI/system/firstPersonHMD.js deleted file mode 100644 index 5fdee1b7b5..0000000000 --- a/scripts/simplifiedUI/system/firstPersonHMD.js +++ /dev/null @@ -1,23 +0,0 @@ -"use strict"; - -// -// firstPersonHMD.js -// system -// -// Created by Zander Otavka on 6/24/16 -// Copyright 2016 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 -// - -(function() { // BEGIN LOCAL_SCOPE - -// Automatically enter first person mode when entering HMD mode -HMD.displayModeChanged.connect(function(isHMDMode) { - if (isHMDMode) { - Camera.setModeString("first person"); - } -}); - -}()); // END LOCAL_SCOPE diff --git a/scripts/simplifiedUI/system/generalSettings.js b/scripts/simplifiedUI/system/generalSettings.js deleted file mode 100644 index d3848da7d0..0000000000 --- a/scripts/simplifiedUI/system/generalSettings.js +++ /dev/null @@ -1,56 +0,0 @@ -"use strict"; - -// -// generalSettings.js -// scripts/system/ -// -// Created by Dante Ruiz on 9 Feb 2017 -// Copyright 2016 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 -// -/* globals Tablet, Toolbars, Script, HMD, DialogsManager */ - -(function() { // BEGIN LOCAL_SCOPE - - var button; - var buttonName = "Settings"; - var toolBar = null; - var tablet = null; - var settings = "hifi/tablet/TabletGeneralPreferences.qml" - function onClicked(){ - if (tablet) { - tablet.loadQMLSource(settings); - } - } - - if (Settings.getValue("HUDUIEnabled")) { - toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); - button = toolBar.addButton({ - objectName: buttonName, - imageURL: Script.resolvePath("assets/images/tools/directory.svg"), - visible: true, - alpha: 0.9 - }); - } else { - tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - button = tablet.addButton({ - icon: "icons/tablet-icons/goto-i.svg", - text: buttonName - }); - } - - button.clicked.connect(onClicked); - - Script.scriptEnding.connect(function () { - button.clicked.disconnect(onClicked); - if (tablet) { - tablet.removeButton(button); - } - if (toolBar) { - toolBar.removeButton(buttonName); - } - }); - -}()); // END LOCAL_SCOPE diff --git a/scripts/simplifiedUI/system/goto.js b/scripts/simplifiedUI/system/goto.js deleted file mode 100644 index 5cc5bad844..0000000000 --- a/scripts/simplifiedUI/system/goto.js +++ /dev/null @@ -1,65 +0,0 @@ -"use strict"; - -// -// goto.js -// scripts/system/ -// -// Created by Howard Stearns on 2 Jun 2016 -// Copyright 2016 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 -// -/* globals Tablet, Toolbars, Script, HMD, DialogsManager */ - -(function() { // BEGIN LOCAL_SCOPE - -var button; -var buttonName = "GOTO"; -var toolBar = null; -var tablet = null; -var onGotoScreen = false; -function onAddressBarShown(visible) { - button.editProperties({isActive: visible}); -} - -function onClicked(){ - DialogsManager.toggleAddressBar(); - onGotoScreen = !onGotoScreen; -} - -if (Settings.getValue("HUDUIEnabled")) { - toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); - button = toolBar.addButton({ - objectName: buttonName, - imageURL: Script.resolvePath("assets/images/tools/directory.svg"), - visible: true, - alpha: 0.9 - }); -} else { - tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - button = tablet.addButton({ - icon: "icons/tablet-icons/goto-i.svg", - activeIcon: "icons/tablet-icons/goto-a.svg", - text: buttonName - }); -} - -button.clicked.connect(onClicked); -DialogsManager.addressBarShown.connect(onAddressBarShown); - -Script.scriptEnding.connect(function () { - if (onGotoScreen) { - DialogsManager.toggleAddressBar(); - } - button.clicked.disconnect(onClicked); - if (tablet) { - tablet.removeButton(button); - } - if (toolBar) { - toolBar.removeButton(buttonName); - } - DialogsManager.addressBarShown.disconnect(onAddressBarShown); -}); - -}()); // END LOCAL_SCOPE diff --git a/scripts/simplifiedUI/system/help.js b/scripts/simplifiedUI/system/help.js deleted file mode 100644 index 40bbf6dbe2..0000000000 --- a/scripts/simplifiedUI/system/help.js +++ /dev/null @@ -1,29 +0,0 @@ -"use strict"; -/* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ -// -// help.js -// scripts/system/ -// -// Created by Howard Stearns on 2 Nov 2016 -// Copyright 2016 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 -// -/* globals Tablet, Script, HMD, Controller, Menu */ - -(function () { // BEGIN LOCAL_SCOPE -var AppUi = Script.require('appUi'); - -var HELP_URL = Script.resourcesPath() + "html/tabletHelp.html"; -var HELP_BUTTON_NAME = "HELP"; -var ui; -function startup() { - ui = new AppUi({ - buttonName: HELP_BUTTON_NAME, - sortOrder: 6, - home: HELP_URL - }); -} -startup(); -}()); // END LOCAL_SCOPE diff --git a/scripts/simplifiedUI/system/hmd.js b/scripts/simplifiedUI/system/hmd.js deleted file mode 100644 index 858b93ef1e..0000000000 --- a/scripts/simplifiedUI/system/hmd.js +++ /dev/null @@ -1,92 +0,0 @@ -"use strict"; - -// -// hmd.js -// scripts/system/ -// -// Created by Howard Stearns on 2 Jun 2016 -// Copyright 2016 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 -// -/* globals HMD, Script, Menu, Tablet, Camera */ -/* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ - -(function() { // BEGIN LOCAL_SCOPE - -var headset; // The preferred headset. Default to the first one found in the following list. -var displayMenuName = "Display"; -var desktopMenuItemName = "Desktop"; -['HTC Vive', 'Oculus Rift', 'WindowMS'].forEach(function (name) { - if (!headset && Menu.menuItemExists(displayMenuName, name)) { - headset = name; - } -}); - -var controllerDisplay = false; -function updateControllerDisplay() { - if (HMD.active && Menu.isOptionChecked("Third Person")) { - if (!controllerDisplay) { - HMD.requestShowHandControllers(); - controllerDisplay = true; - } - } else if (controllerDisplay) { - HMD.requestHideHandControllers(); - controllerDisplay = false; - } -} - -var button; -var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - -var switchToVR = "ENTER VR"; -var switchToDesktop = "EXIT VR"; - -function onHmdChanged(isHmd) { - HMD.closeTablet(); - if (isHmd) { - button.editProperties({ - icon: "icons/tablet-icons/switch-desk-i.svg", - text: switchToDesktop - }); - } else { - button.editProperties({ - icon: "icons/tablet-icons/switch-vr-i.svg", - text: switchToVR - }); - } - updateControllerDisplay(); -} - -function onClicked() { - var isDesktop = Menu.isOptionChecked(desktopMenuItemName); - Menu.setIsOptionChecked(isDesktop ? headset : desktopMenuItemName, true); - if (!isDesktop) { - UserActivityLogger.logAction("exit_vr"); - } -} - -if (headset) { - button = tablet.addButton({ - icon: HMD.active ? "icons/tablet-icons/switch-desk-i.svg" : "icons/tablet-icons/switch-vr-i.svg", - text: HMD.active ? switchToDesktop : switchToVR, - sortOrder: 2 - }); - onHmdChanged(HMD.active); - - button.clicked.connect(onClicked); - HMD.displayModeChanged.connect(onHmdChanged); - Camera.modeUpdated.connect(updateControllerDisplay); - - Script.scriptEnding.connect(function () { - button.clicked.disconnect(onClicked); - if (tablet) { - tablet.removeButton(button); - } - HMD.displayModeChanged.disconnect(onHmdChanged); - Camera.modeUpdated.disconnect(updateControllerDisplay); - }); -} - -}()); // END LOCAL_SCOPE diff --git a/scripts/simplifiedUI/system/html/ChatPage.html b/scripts/simplifiedUI/system/html/ChatPage.html deleted file mode 100644 index 9606eeab3e..0000000000 --- a/scripts/simplifiedUI/system/html/ChatPage.html +++ /dev/null @@ -1,511 +0,0 @@ - - - - Chat - - - - - - - - -
- -
- Chat -
- -
- -
- -
- -
- - - - - - diff --git a/scripts/simplifiedUI/system/html/EmoteApp.html b/scripts/simplifiedUI/system/html/EmoteApp.html deleted file mode 100644 index 6b42fb8dc8..0000000000 --- a/scripts/simplifiedUI/system/html/EmoteApp.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - Emote App - - - - - - -
-

Emote App

-
-
-

Choose an emote:

-

-

-

-

-

-

-

-

-

-

-
- - - - - \ No newline at end of file diff --git a/scripts/simplifiedUI/system/html/SnapshotReview.html b/scripts/simplifiedUI/system/html/SnapshotReview.html deleted file mode 100644 index f080cd204a..0000000000 --- a/scripts/simplifiedUI/system/html/SnapshotReview.html +++ /dev/null @@ -1,38 +0,0 @@ - - - Share - - - - - - - -
- - - -
-
-
-
-
-
-
-
-
-
- -
- -
-
- -
- -
-
- - diff --git a/scripts/simplifiedUI/system/html/css/SnapshotReview.css b/scripts/simplifiedUI/system/html/css/SnapshotReview.css deleted file mode 100644 index 54d39aaad3..0000000000 --- a/scripts/simplifiedUI/system/html/css/SnapshotReview.css +++ /dev/null @@ -1,346 +0,0 @@ -/* -// SnapshotReview.css -// -// Created by Howard Stearns for David Rowe 8/22/2016. -// Copyright 2016 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 -*/ - -/* -// START styling of top bar and its contents -*/ - -.title { - padding: 6px 10px; - text-align: left; - height: 26px; - line-height: 26px; - clear: both; -} - -.title label { - position: relative; - font-size: 18px; - float: left; -} - -#snapshotSettings { - position: relative; - float: right; -} -#settingsLabel { - position: relative; - float: right; - font-family: Raleway-SemiBold; - font-size: 14px; -} -.hifi-glyph { - font-size: 30px; - top: -4px; -} -input[type=button].naked { - color: #afafaf; - background: none; -} -input[type=button].naked:hover { - color: #ffffff; -} -input[type=button].naked:active { - color: #afafaf; -} -/* -// END styling of top bar and its contents -*/ - -/* -// START styling of snapshot instructions panel -*/ -.snapshotInstructions { - font-family: Raleway-Regular; - margin: 0 20px; - width: 100%; - height: 50%; -} -/* -// END styling of snapshot instructions panel -*/ - -/* -// START styling of snapshot pane and its contents -*/ -#snapshot-pane { - width: 100%; - height: 560px; - display: flex; - justify-content: center; - align-items: center; -} - -#snapshot-images { - width: 100%; - display: flex; - justify-content: center; - flex-direction: column; -} - -#snapshot-images img { - max-width: 100%; - max-height: 100%; -} - -.gifLabel { - position:absolute; - left: 15px; - top: 10px; - font-family: Raleway-SemiBold; - font-size: 18px; - color: white; - text-shadow: 2px 2px 3px #000000; -} -/* -// END styling of snapshot pane and its contents -*/ - -/* -// START styling of share overlay -*/ -.shareControls { - display: flex; - justify-content: space-between; - flex-direction: row; - align-items: center; - height: 65px; - line-height: 65px; - width: calc(100% - 8px); - position: absolute; - bottom: 4px; - left: 4px; - right: 4px; -} -.showShareButtonsButtonDiv { - display: inline-flex; - align-items: center; - font-family: Raleway-SemiBold; - font-size: 14px; - color: white; - width: 75px; - height: 100%; - margin-bottom: 0px; -} -.showShareButtonsButtonDiv.active:hover { - background-color: rgba(0, 0, 0, 0.45); - background-size: 2px; -} -.showShareButtonsButtonDiv > label { - text-shadow: 2px 2px 3px #000000; - margin-bottom: -14px; - margin-left: 12px; -} -.showShareButtonsButtonDiv:hover > label { - text-shadow: none; -} -.showShareButtonDots { - display: block; - width: 40px; - height: 40px; - font-family: HiFi-Glyphs; - font-size: 60px; - position: absolute; - left: 6px; - bottom: 32px; - color: white; - pointer-events: none; -} -.shareButtons { - display: flex; - align-items: flex-end; - height: 40px; - width: calc(100% - 60px); - margin-bottom: -24px; - margin-left: 0; -} -.shareButtons img { - width: 40px; - height: 40px; -} -.shareButton { - width: 40px; - height: 40px; - display: inline-block; -} -.shareButton.disabled { - background-color: #000000; - opacity: 0.5; -} -.shareControlsHelp { - height: 25px; - line-height: 25px; - position: absolute; - bottom: 40px; - left: 73px; - right: 0; - font-family: Raleway-Regular; - font-weight: 500; - font-size: 16px; - padding-left: 8px; - color: white; -} -.helpTextDiv { - width: 350px; - height: 65px; - margin-right: 15px; - line-height: 65px; - position: absolute; - bottom: 0; - right: 0; - font-family: Raleway-Regular; - font-weight: 500; - font-size: 16px; - color: white; -} -/* -// END styling of share overlay -*/ - -/* -// START styling of confirmation message -*/ -.confirmationMessageContainer { - width: 100%; - height: 100%; - position: absolute; - background-color: rgba(0, 0, 0, 0.45); - text-align: center; - left: 0; - top: 0; - pointer-events: none; - color: white; - font-weight: bold; - font-size: 16px; -} -.confirmationMessage { - width: 130px; - height: 130px; - margin: 50px auto 0 auto; -} -.confirmationMessage > img { - width: 72px; - height: 72px; - display: block; - margin: 0 auto; - padding: 10px 0 0 0; -} -/* -// END styling of uploading message -*/ - -/* -// START styling of snapshot controls (bottom panel) and its contents -*/ -#snapshot-controls { - width: 100%; - position: absolute; - left: 0; - overflow: hidden; - display: flex; - justify-content: center; -} -#snap-settings { - display: inline; - width: 150px; - margin: 2px auto 0 auto; -} -#snap-settings form input { - margin-bottom: 5px; -} - -#snap-button { - width: 72px; - height: 72px; - padding: 0; - border-radius: 50%; - background: #EA4C5F; - border: 3px solid white; - margin: 2px auto 0 auto; - box-sizing: content-box; - display: inline; - outline:none; -} -#snap-button:disabled { - background: gray; -} -#snap-button:hover:enabled { - background: #C62147; -} -#snap-button:active:enabled { - background: #EA4C5F; -} -#snap-settings-right { - display: inline; - width: 150px; - margin: auto; -} -/* -// END styling of snapshot controls (bottom panel) and its contents -*/ - - -/* -// START polaroid styling -*/ - -#print-button { - width: 72px; - height: 72px; - margin-left: 30px; - margin-top: -10px; - box-sizing: content-box; - display: inline; - outline:none; -} - -.print-icon { - margin: auto; -} - -.print-icon-default { - background: url(../img/button-snap-print.svg) no-repeat; - margin-right: -1px; - width: 64px; - height: 64px; -} - -.print-icon-loading { - background: url(../img/loader.gif) no-repeat; - width: 32px; - height: 32px; -} - -/* -// END polaroid styling -*/ - - -/* -// START misc styling -*/ -body { - padding: 0; - margin: 0; - overflow: hidden; -} -p { - margin: 2px 0; -} -h4 { - margin: 14px 0 0 0; -} -.centeredImage { - margin: 0 auto; - display: block; -} -/* -// END misc styling -*/ diff --git a/scripts/simplifiedUI/system/html/css/colpick.css b/scripts/simplifiedUI/system/html/css/colpick.css deleted file mode 100644 index fc50c4b3fb..0000000000 --- a/scripts/simplifiedUI/system/html/css/colpick.css +++ /dev/null @@ -1,433 +0,0 @@ -/* -colpick Color Picker / colpick.com -*/ - -/*Main container*/ -.colpick { - position: absolute; - width: 346px; - height: 170px; - overflow: hidden; - display: none; - font-family: Arial, Helvetica, sans-serif; - background:#ebebeb; - border: 1px solid #bbb; - -webkit-border-radius: 5px; - -moz-border-radius: 5px; - border-radius: 5px; - - /*Prevents selecting text when dragging the selectors*/ - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - -o-user-select: none; - user-select: none; -} -/*Color selection box with gradients*/ -.colpick_color { - position: absolute; - touch-action: none; - left: 7px; - top: 7px; - width: 156px; - height: 156px; - overflow: hidden; - outline: 1px solid #aaa; - cursor: crosshair; -} -.colpick_color_overlay1 { - position: absolute; - left:0; - top:0; - width: 156px; - height: 156px; - -ms-filter: "progid:DXImageTransform.Microsoft.gradient(GradientType=1,startColorstr='#ffffff', endColorstr='#00ffffff')"; /* IE8 */ - background: -moz-linear-gradient(left, rgba(255,255,255,1) 0%, rgba(255,255,255,0) 100%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, right top, color-stop(0%,rgba(255,255,255,1)), color-stop(100%,rgba(255,255,255,0))); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(left, rgba(255,255,255,1) 0%,rgba(255,255,255,0) 100%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(left, rgba(255,255,255,1) 0%,rgba(255,255,255,0) 100%); /* Opera 11.10+ */ - background: -ms-linear-gradient(left, rgba(255,255,255,1) 0%,rgba(255,255,255,0) 100%); /* IE10+ */ - background: linear-gradient(to right, rgba(255,255,255,1) 0%, rgba(255,255,255,0) 100%); - filter: progid:DXImageTransform.Microsoft.gradient(GradientType=1,startColorstr='#ffffff', endColorstr='#00ffffff'); /* IE6 & IE7 */ -} -.colpick_color_overlay2 { - position: absolute; - left:0; - top:0; - width: 156px; - height: 156px; - -ms-filter: "progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr='#00000000', endColorstr='#000000')"; /* IE8 */ - background: -moz-linear-gradient(top, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 100%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(0,0,0,0)), color-stop(100%,rgba(0,0,0,1))); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, rgba(0,0,0,0) 0%,rgba(0,0,0,1) 100%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, rgba(0,0,0,0) 0%,rgba(0,0,0,1) 100%); /* Opera 11.10+ */ - background: -ms-linear-gradient(top, rgba(0,0,0,0) 0%,rgba(0,0,0,1) 100%); /* IE10+ */ - background: linear-gradient(to bottom, rgba(0,0,0,0) 0%,rgba(0,0,0,1) 100%); /* W3C */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00000000', endColorstr='#000000',GradientType=0 ); /* IE6-9 */ -} -/*Circular color selector*/ -.colpick_selector_outer { - background:none; - position: absolute; - width: 11px; - height: 11px; - margin: -6px 0 0 -6px; - border: 1px solid black; - border-radius: 50%; -} -.colpick_selector_inner{ - position: absolute; - width: 9px; - height: 9px; - border: 1px solid white; - border-radius: 50%; -} -/*Vertical hue bar*/ -.colpick_hue { - position: absolute; - touch-action: none; - top: 6px; - left: 175px; - width: 19px; - height: 156px; - border: 1px solid #aaa; - cursor: n-resize; -} -/*Hue bar sliding indicator*/ -.colpick_hue_arrs { - position: absolute; - touch-action: none; - left: -8px; - width: 35px; - height: 7px; - margin: -7px 0 0 0; -} -.colpick_hue_larr { - position:absolute; - touch-action: none; - width: 0; - height: 0; - border-top: 6px solid transparent; - border-bottom: 6px solid transparent; - border-left: 7px solid #858585; -} -.colpick_hue_rarr { - position:absolute; - touch-action: none; - right:0; - width: 0; - height: 0; - border-top: 6px solid transparent; - border-bottom: 6px solid transparent; - border-right: 7px solid #858585; -} -/*New color box*/ -.colpick_new_color { - position: absolute; - touch-action: none; - left: 207px; - top: 6px; - width: 60px; - height: 27px; - background: #f00; - border: 1px solid #8f8f8f; -} -/*Current color box*/ -.colpick_current_color { - position: absolute; - touch-action: none; - left: 277px; - top: 6px; - width: 60px; - height: 27px; - background: #f00; - border: 1px solid #8f8f8f; -} -/*Input field containers*/ -.colpick_field, .colpick_hex_field { - position: absolute; - touch-action: none; - height: 20px; - width: 60px; - overflow:hidden; - background:#f3f3f3; - color:#b8b8b8; - font-size:12px; - border:1px solid #bdbdbd; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} -.colpick_rgb_r { - top: 40px; - left: 207px; -} -.colpick_rgb_g { - top: 67px; - left: 207px; -} -.colpick_rgb_b { - top: 94px; - left: 207px; -} -.colpick_hsb_h { - top: 40px; - left: 277px; -} -.colpick_hsb_s { - top: 67px; - left: 277px; -} -.colpick_hsb_b { - top: 94px; - left: 277px; -} -.colpick_hex_field { - width: 68px; - left: 207px; - top: 121px; -} -/*Text field container on focus*/ -.colpick_focus { - border-color: #999; -} -/*Field label container*/ -.colpick_field_letter { - position: absolute; - width: 12px; - height: 20px; - line-height: 20px; - padding-left: 4px; - background: #efefef; - border-right: 1px solid #bdbdbd; - font-weight: bold; - color:#777; -} -/*Text inputs*/ -.colpick_field input, .colpick_hex_field input { - position: absolute; - touch-action: none; - right: 11px; - margin: 0; - padding: 0; - height: 20px; - line-height: 20px; - background: transparent; - border: none; - font-size: 12px; - font-family: Arial, Helvetica, sans-serif; - color: #555; - text-align: right; - outline: none; -} -.colpick_hex_field input { - right: 4px; -} -/*Field up/down arrows*/ -.colpick_field_arrs { - position: absolute; - touch-action: none; - top: 0; - right: 0; - width: 9px; - height: 21px; - cursor: n-resize; -} -.colpick_field_uarr { - position: absolute; - touch-action: none; - top: 5px; - width: 0; - height: 0; - border-left: 4px solid transparent; - border-right: 4px solid transparent; - border-bottom: 4px solid #959595; -} -.colpick_field_darr { - position: absolute; - touch-action: none; - bottom:5px; - width: 0; - height: 0; - border-left: 4px solid transparent; - border-right: 4px solid transparent; - border-top: 4px solid #959595; -} -/*Submit/Select button*/ -.colpick_submit { - position: absolute; - touch-action: none; - left: 207px; - top: 149px; - width: 130px; - height: 22px; - line-height:22px; - background: #efefef; - text-align: center; - color: #555; - font-size: 12px; - font-weight:bold; - border: 1px solid #bdbdbd; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} -.colpick_submit:hover { - background:#f3f3f3; - border-color:#999; - cursor: pointer; -} - -/*full layout with no submit button*/ -.colpick_full_ns .colpick_submit { - display:none; -} -.colpick_full_ns .colpick_new_color { - width: 130px; - height: 25px; -} -.colpick_full_ns .colpick_rgb_r, .colpick_full_ns .colpick_hsb_h { - top: 42px; -} -.colpick_full_ns .colpick_rgb_g, .colpick_full_ns .colpick_hsb_s { - top: 73px; -} -.colpick_full_ns .colpick_rgb_b, .colpick_full_ns .colpick_hsb_b { - top: 104px; -} -.colpick_full_ns .colpick_hex_field { - top: 135px; -} - -/*rgbhex layout*/ -.colpick_rgbhex .colpick_hsb_h, .colpick_rgbhex .colpick_hsb_s, .colpick_rgbhex .colpick_hsb_b { - display:none; -} -.colpick_rgbhex { - width:282px; -} -.colpick_rgbhex .colpick_field, .colpick_rgbhex .colpick_submit { - width:68px; -} -.colpick_rgbhex .colpick_new_color { - width:34px; - border-right:none; -} -.colpick_rgbhex .colpick_current_color { - width:34px; - left:240px; - border-left:none; -} - -/*rgbhex layout, no submit button*/ -.colpick_rgbhex_ns .colpick_submit { - display:none; -} -.colpick_rgbhex_ns .colpick_new_color{ - width:34px; - border: 1px solid #8f8f8f; -} -.colpick_rgbhex_ns .colpick_rgb_r { - top: 42px; -} -.colpick_rgbhex_ns .colpick_rgb_g { - top: 73px; -} -.colpick_rgbhex_ns .colpick_rgb_b { - top: 104px; -} -.colpick_rgbhex_ns .colpick_hex_field { - top: 135px; -} - -/*hex layout*/ -.colpick_hex .colpick_hsb_h, .colpick_hex .colpick_hsb_s, .colpick_hex .colpick_hsb_b, .colpick_hex .colpick_rgb_r, .colpick_hex .colpick_rgb_g, .colpick_hex .colpick_rgb_b { - display:none; -} -.colpick_hex { - width:206px; - height:201px; -} -.colpick_hex .colpick_hex_field { - width:72px; - height:25px; - top:168px; - left:80px; -} -.colpick_hex .colpick_hex_field div, .colpick_hex .colpick_hex_field input { - height: 25px; - line-height: 25px; -} -.colpick_hex .colpick_new_color { - left:9px; - top:168px; - width:30px; - border-right:none; -} -.colpick_hex .colpick_current_color { - left:39px; - top:168px; - width:30px; - border-left:none; -} -.colpick_hex .colpick_submit { - left:164px; - top: 168px; - width:30px; - height:25px; - line-height: 25px; -} - -/*hex layout, no submit button*/ -.colpick_hex_ns .colpick_submit { - display:none; -} -.colpick_hex_ns .colpick_hex_field { - width:80px; -} -.colpick_hex_ns .colpick_new_color{ - width:60px; - border: 1px solid #8f8f8f; -} - -/*Dark color scheme*/ -.colpick_dark { - background: #161616; - border-color: #2a2a2a; -} -.colpick_dark .colpick_color { - outline-color: #333; -} -.colpick_dark .colpick_hue { - border-color: #555; -} -.colpick_dark .colpick_field, .colpick_dark .colpick_hex_field { - background: #101010; - border-color: #2d2d2d; -} -.colpick_dark .colpick_field_letter { - background: #131313; - border-color: #2d2d2d; - color: #696969; -} -.colpick_dark .colpick_field input, .colpick_dark .colpick_hex_field input { - color: #7a7a7a; -} -.colpick_dark .colpick_field_uarr { - border-bottom-color:#696969; -} -.colpick_dark .colpick_field_darr { - border-top-color:#696969; -} -.colpick_dark .colpick_focus { - border-color:#444; -} -.colpick_dark .colpick_submit { - background: #131313; - border-color:#2d2d2d; - color:#7a7a7a; -} -.colpick_dark .colpick_submit:hover { - background-color:#101010; - border-color:#444; -} \ No newline at end of file diff --git a/scripts/simplifiedUI/system/html/css/edit-style.css b/scripts/simplifiedUI/system/html/css/edit-style.css deleted file mode 100644 index 470e57ad6d..0000000000 --- a/scripts/simplifiedUI/system/html/css/edit-style.css +++ /dev/null @@ -1,1796 +0,0 @@ -/* -// edit-style.css -// -// Created by Ryan Huffman on 13 Nov 2014 -// Copyright 2014 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 -*/ - -@font-face { - font-family: Raleway-Regular; - src: url(../../../../resources/fonts/Raleway-Regular.ttf), /* Windows production */ - url(../../../../fonts/Raleway-Regular.ttf), /* OSX production */ - url(../../../../interface/resources/fonts/Raleway-Regular.ttf), /* Development, running script in /HiFi/examples */ - url(../fonts/Raleway-Regular.ttf); /* Marketplace script */ -} - -@font-face { - font-family: Raleway-Light; - src: url(../../../../resources/fonts/Raleway-Light.ttf), - url(../../../../fonts/Raleway-Light.ttf), - url(../../../../interface/resources/fonts/Raleway-Light.ttf), - url(../fonts/Raleway-Light.ttf); -} - -@font-face { - font-family: Raleway-Bold; - src: url(../../../../resources/fonts/Raleway-Bold.ttf), - url(../../../../fonts/Raleway-Bold.ttf), - url(../../../../interface/resources/fonts/Raleway-Bold.ttf), - url(../fonts/Raleway-Bold.ttf); -} - -@font-face { - font-family: Raleway-SemiBold; - src: url(../../../../resources/fonts/Raleway-SemiBold.ttf), - url(../../../../fonts/Raleway-SemiBold.ttf), - url(../../../../interface/resources/fonts/Raleway-SemiBold.ttf), - url(../fonts/Raleway-SemiBold.ttf); -} - -@font-face { - font-family: FiraSans-SemiBold; - src: url(../../../../resources/fonts/FiraSans-SemiBold.ttf), - url(../../../../fonts/FiraSans-SemiBold.ttf), - url(../../../../interface/resources/fonts/FiraSans-SemiBold.ttf), - url(../fonts/FiraSans-SemiBold.ttf); -} - -@font-face { - font-family: AnonymousPro-Regular; - src: url(../../../../resources/fonts/AnonymousPro-Regular.ttf), - url(../../../../fonts/AnonymousPro-Regular.ttf), - url(../../../../interface/resources/fonts/AnonymousPro-Regular.ttf), - url(../fonts/AnonymousPro-Regular.ttf); -} - -@font-face { - font-family: HiFi-Glyphs; - src: url(../../../../resources/fonts/hifi-glyphs.ttf), - url(../../../../fonts/hifi-glyphs.ttf), - url(../../../../interface/resources/fonts/hifi-glyphs.ttf), - url(../fonts/hifi-glyphs.ttf); -} - -* { - margin: 0; - padding: 0; -} - -body { - - color: #afafaf; - background-color: #404040; - font-family: Raleway-Regular; - font-size: 12px; - - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - - overflow-x: hidden; - overflow-y: auto; -} - -table { - font-family: FiraSans-SemiBold; - font-size: 15px; - color: #afafaf; - border-collapse: collapse; - width: 100%; - border: 2px solid #575757; - border-radius: 7px; -} - -thead { - font-family: Raleway-Regular; - font-size: 12px; - text-transform: uppercase; - background-color: #1c1c1c; - padding: 1px 0; - border-bottom: 1px solid #575757; - width: 100%; -} - -tbody { - width: 100%; - display: block; -} - -tfoot { - font-family: Raleway-Light; - font-size: 13px; - background-color: #1c1c1c; - border-top: 1px solid #575757; - width: 100%; -} - -tfoot tr { - background-color: #1c1cff; -} - -thead tr { - height: 26px; /* 28px with thead padding */ -} - -thead th { - height: 26px; - background-color: #1c1c1c; - border-right: 1px solid #575757; -} - -thead th:last-child { - border: none; -} - -tbody td { - height: 26px; -} - -tfoot td { - height: 18px; - width: 100%; - background-color: #1c1c1c; - margin-left: 12px; -} - -tr { - width: 100%; - cursor: pointer; -} - -tr:nth-child(odd) { - background-color: #2e2e2e; -} - -tr:nth-child(even) { - background-color: #1c1c1c; -} - -tr:focus { - outline: none; -} - -tr.selected { - color: #000000; - background-color: #00b4ef; -} - -tr.selected + tr.selected { - border-top: 1px solid #2e2e2e; -} - -th { - text-align: center; - word-wrap: nowrap; - white-space: nowrap; - padding-left: 12px; - padding-right: 12px; -} - -td { - overflow: hidden; - text-overflow: clip; - white-space: nowrap; - word-wrap: nowrap; - padding-left: 12px; - padding-right: 12px; -} - -td.hidden { - padding-left: 0; - padding-right: 0; -} - -td.url { - white-space: nowrap; - overflow: hidden; -} - - -input[type="text"], input[type="search"], input[type="number"], textarea { - margin: 0; - padding: 0 12px; - color: #afafaf; - background-color: #252525; - border: none; - font-family: FiraSans-SemiBold; - font-size: 15px; -} - -textarea { - font-family: AnonymousPro-Regular; - font-size: 16px; - padding-top: 5px; - padding-bottom: 5px; - min-height: 64px; - width: 100%; - resize: vertical; -} - -input::-webkit-input-placeholder { - font-style: italic; -} - -input:focus, textarea:focus, button:focus { - color: #fff; - background-color: #000; - outline: 1px solid #00b4ef; - outline-offset: -1px; -} - -input::selection, textarea::selection { - color: #000000; - background-color: #00b4ef; -} - -input.search { - border-radius: 14px; -} - -input.search:focus { - outline: none; - box-sizing: border-box; - height: 26px; - margin-top: 1px; - margin-bottom: 1px; - box-shadow: 0 0 0 1px #00b4ef; -} - -input:disabled, textarea:disabled, .draggable-number.text[disabled="disabled"] { - background-color: #383838; - color: #afafaf; -} - -input[type="text"] { - height: 28px; - width: 100%; -} - -input.multi-diff:not(:focus) + span.multi-diff, -textarea.multi-diff:not(:focus) + span.multi-diff, -.draggable-number.multi-diff>input:not(:focus)+span.multi-diff, -dl>dt.multi-diff:not(:focus) + span.multi-diff { - visibility: visible; - position: absolute; - display: inline-block; - z-index: 2; - top: 7.5px; - left: 20px; - max-width: 50px; - min-width: 10px; - width: 50%; - height: 13px; - background-image: linear-gradient(transparent 0%, transparent 10%, #afafaf 10%, #afafaf 20%, transparent 20%, transparent 45%, #afafaf 45%, #afafaf 55%, transparent 55%, transparent 80%, #afafaf 80%, #afafaf 90%, transparent 90%, transparent 100%); - background-repeat: no-repeat; - pointer-events: none; -} - -input.multi-diff:not(:focus)::-webkit-input-placeholder, input.multi-diff:not(:focus) { - color: transparent; -} - -.draggable-number.multi-diff .text { - color: transparent; -} - -.dropdown > span.multi-diff { - top: 5px; - left: 10px; -} - -.text, .url, .texture, .textarea { - position: relative; -} - -input[type="search"] { - height: 28px; - width: 100%; -} -input[type="search"]::-webkit-search-cancel-button { - -webkit-appearance: none; - height: 20px; - width: 20px; - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAB3RJTUUH4goNAQIFbBwsbwAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAZfSURBVDgRAVQGq/kAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9PT0YAwMDBgAAAAD8/Pz5+vr67MrKyv0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA+Pj4KAgICQgAAAE3///9RAQEBFQAAAAD////pAQEBu/39/ab+/v7BxcXF9gAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAADs7OzMEBASIAQEBRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAACm+/v7cMXFxewAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAPT09OwEBAagBAQEcAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAA2f///2XCwsLDAAAAAAAAAAABAAAAAAAAAAA9PT0KAwMDt////z4AAAAAAAAAAAEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAcIBAQFJvr6+9gAAAAACAAAAAAAAAAAAAABg////PgEBAQAAAAAAS0tLADg4OAAAAAAAAAAAAP///wADAwMAQEBAACEhIQD///8A////AP7+/j76+vpWAAAAAAAAAAACAAAAAD09PQ8CAgJkAQEBAP///wD///8ACgoKAFhYWAAyMjIAAAAAAAICAgBGRkYAT09PABEREQAAAAAAAAAAAAAAAAACAgJwOjo6EAAAAAAEAAAAAAICAg8BAQExAAAAAAEBAQABAQEAsrKyAAoKCgBaWloA9/f3ABsbGwBISEgAtra2AM7OzgACAgIA////AP///wABAQEuBQUFDgAAAPAEAAAAAPz8/BkEBAQAAQEBAAAAAAAAAAAA+vr6AKioqAALCwsAZWVlAAcHBwC/v78Au7u7AAEBAQD///8AAAAAAAAAAAAAAAABAAAAAAAAAAACAAAAAAQEBOgBAQEAAQEBAAEBAQABAQEAAQEBAPz8/ADT09MADg4OAP39/QDQ0NAA/v7+AP///wAAAAAAAAAAAAEBAQABAQEAAQEBAAAAAAACAAAAAAAAAP8AAAD/AAAAAAAAAAAAAAAAAAAAACkpKQBQUFAAx8fHAObm5gBfX18AFxcXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAP39/fz+/v7z////AP///wD///8AJycnAGFhYQDc3NwApaWlAJaWlgD29vYAZmZmABQUFAACAgIAAQEBAAEBAQABAQH1AAAA/AAAAAACAAAAAPr6+ukBAQGkAAAAAAAAAAABAQEAQEBAAObm5gCmpqYA+fn5APPz8wCdnZ0A////ACwsLAD///8AAAAAAAAAAAD///+k9vb26QAAAAABAAAAAAAAAAA+Pj4uAgICxgAAAAsAAAAAEBAQAPr6+gD29vYAAAAAAAAAAAABAQEAAgICAP///wD+/v4AAAAAAAAAAPL8/Pw/xMTE0AAAAAACAAAAAAAAAAD5+fnV////nQICAgABAQEA8fHxAPX19QABAQEAAAAAAAAAAAD///8A/v7+AP7+/gAAAAAAAAAAAP7+/p36+vrSAAAAAAAAAAADAAAAAAAAAADl5eX/ICAgwQAAAA////8q////BgEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1/f39mAEBAXrGxsb7AAAAAAAAAAADAAAAAAAAAAAAAAAA4eHh/BgYGLsBAQHDBAQEHAAAACP///8AAQEBAAAAAAAAAAAAAAAA+////7QBAQFu+fn5m8bGxvoAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPz8/Cv7+/iUBAQFMAgICEQICAgD8/PzdAwMDs/j4+OvHx8f5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8TUnpZ7EwQgAAAABJRU5ErkJggg==') -} - -input[type="number"] { - position: relative; - height: 28px; - width: 124px; -} -input[type=number] { - padding-right: 3px; -} -input[type=number]::-webkit-inner-spin-button { - opacity: 1.0; - display: block; - position: relative; - width: 10px; - height: 90%; - overflow: hidden; - font-family: HiFi-Glyphs; - font-size: 32px; - color: #afafaf; - cursor: pointer; - background-color: #000000; -} -input[type=number]::-webkit-inner-spin-button:before, -input[type=number]::-webkit-inner-spin-button:after { - position:absolute; - left: -19px; - line-height: 8px; - text-align: center; -} -input[type=number]::-webkit-inner-spin-button:before { - content: "6"; - top: 4px; -} -input[type=number]::-webkit-inner-spin-button:after { - content: "5"; - bottom: 4px; -} - -input[type=number].hover-up::-webkit-inner-spin-button:before, -input[type=number].hover-down::-webkit-inner-spin-button:after { - color: #ffffff; -} - -input[type=range] { - -webkit-appearance: none; - background: #2e2e2e; - height: 1.8rem; - border-radius: 1rem; -} -input[type=range]::-webkit-slider-thumb { - -webkit-appearance:none; - width: 0.6rem; - height: 1.8rem; - padding:0; - margin: 0; - background-color: #696969; - border-radius: 1rem; -} -input[type=range]::-webkit-slider-thumb:hover { - background-color: white; -} -input[type=range]:focus { - outline: none; -} - -input.no-spin::-webkit-outer-spin-button, -input.no-spin::-webkit-inner-spin-button { - display: none; - -webkit-appearance: none; - margin: 0; /* <-- Apparently some margin are still there even though it's hidden */ - padding-right: 12px; -} - -input[type=button], button.hifi-edit-button { - font-family: Raleway-Bold; - font-size: 13px; - text-transform: uppercase; - vertical-align: top; - height: 28px; - min-width: 120px; - padding: 0 18px; - margin-right: 6px; - border-radius: 5px; - border: none; - color: #fff; - background-color: #000; - background: linear-gradient(#343434 20%, #000 100%); - cursor: pointer; -} - -input[type=button].glyph, button.hifi-edit-button.glyph { - font-family: HiFi-Glyphs; - font-size: 20px; - text-transform: none; - min-width: 32px; - padding: 0; -} - -input[type=button].red, button.hifi-edit-button.red { - color: #fff; - background-color: #94132e; - background: linear-gradient(#d42043 20%, #94132e 100%); -} -input[type=button].blue, button.hifi-edit-button.blue { - color: #fff; - background-color: #1080b8; - background: linear-gradient(#00b4ef 20%, #1080b8 100%); -} -input[type=button].white, button.hifi-edit-button.white { - color: #121212; - background-color: #afafaf; - background: linear-gradient(#fff 20%, #afafaf 100%); -} - -input[type=button]:enabled:hover, button.hifi-edit-button:enabled:hover { - background: linear-gradient(#000, #000); - border: none; -} -input[type=button].red:enabled:hover, button.hifi-edit-button.red:enabled:hover { - background: linear-gradient(#d42043, #d42043); - border: none; -} -input[type=button].blue:enabled:hover, button.hifi-edit-button.blue:enabled:hover { - background: linear-gradient(#00b4ef, #00b4ef); - border: none; -} -input[type=button].white:enabled:hover, button.hifi-edit-button.white:enabled:hover { - background: linear-gradient(#fff, #fff); - border: none; -} - -input[type=button]:active, button.hifi-edit-button:active { - background: linear-gradient(#343434, #343434); -} -input[type=button].red:active, button.hifi-edit-button.red:active { - background: linear-gradient(#94132e, #94132e); -} -input[type=button].blue:active, button.hifi-edit-button.blue:active { - background: linear-gradient(#1080b8, #1080b8); -} -input[type=button].white:active, button.hifi-edit-button.white:active { - background: linear-gradient(#afafaf, #afafaf); -} - -input[type=button]:disabled, button.hifi-edit-button:disabled { - color: #252525; - background: linear-gradient(#575757 20%, #252525 100%); -} - -input[type=button][pressed=pressed], button.hifi-edit-button[pressed=pressed] { - color: #00b4ef; -} - -input[type=checkbox] { - display: none; -} -input[type=checkbox] + label { - padding-left: 24px; - background-repeat: no-repeat; - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACpSURBVDhPY2xoaGD68+dPMSMjY9L////VgTQjAw4AlH8PxLOPHj1azWxjY1MBVNsBFBfBpwkEgNKcQGwtJyfHyATkF0KEiQdAzYlMQEIUyicFyDD9+/ePgRxMvsb///4zkIOZ/v0HmkAGHginYjGNGAzS+BpdkAj8mun/3//92DyPD//993cG88nTJ4+Zm5p/BSZeJYb/DEJADEzNOPF7hn8Mk69cvVIPAHN5pyfo70F5AAAAAElFTkSuQmCC); - cursor: pointer; -} -input[type=checkbox]:enabled + label:hover { - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAClSURBVDhPY2hoaGD6//9/6b9//64D8T8gGycASr/7+/dv5/79+1kYgIxKqDjRAKiniRFIv2JgYBAFYlLAE0aQ66AckgDjjx8/yNP44cMH8jS+fPmSPI0PHz4kT+PNmzfJ03jp0iXyNJ46dYo8jYcPHyYnAbxm+vnzZz8wLhlIwd+/f5/BrKSkdExCQuLrnz9/lIBpUAiIQekXF34PTGmTT548WQ8AokXg+rhVtPYAAAAASUVORK5CYII=); -} -input[type=checkbox]:checked + label { - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFLSURBVDhPjZK9SgNBFIXvbCaQRDQq7mIhQRPBRisJKcwLWOobaCsExEaxcEEQe0trGysfwg0EwWoDsbFIJUaIBJOwus547saNP3FlPzgzzJxzL5edFbZtG77v7wkhtrXWS9gFRQC/DZ07jnOYKJfL+8ie4n7mvyIGdhpay+VyQuK8y5dPZoHuVtbpZcLi4wjJ1x4t316R9dDgBlsSi8mGu7pJjyJFzVaH+r7iqyHSELSQzVADjS0UgjlDKUUsLzVO98+9kSLGV5qaHXhjU0GWNSxk3hCIwnsfeMNCjTArLmHeUBodoLiE+R+jxuHPUZP4elGE3teonx2S/Q7lJzOUlkYQ+A4/xzyegzNhXmJpwTMXry9IFjcoa84O0r+QXpcK1cugCLREZadyoA19Ergxwf96nKjd1KqlYqmLQ540TUNwItUmRWdu3T36AODjwgpY9xqqAAAAAElFTkSuQmCC); -} -input[type=checkbox]:checked + label:hover { - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEySURBVDhPnZLPSsNAEMa/XVPBCE0RhNy0OarP4Av4AD6JB0GwVBA8efBBxHsgh4CQswcRoUIpiIpVAm3zZ5M4szFSbQPBH3xkJvNNZskOer2eLIriKM/ze1JOcS1UHmdZduF5ngEKjr/fN4Z6+oKerwA2gxC4HAFPEWVLsAzgZAvYt3Q6Enw6jg7uBAaTFMNwhpnKdbXCkAJdy8ROu4XrXW2HTJIErHcFDD6nC02Mom8PwymeE2gvS0ZRBBaTlsOXEmdlrfLLOI7Bakrl/zWxCT8T/904f9QW/b06qtrCUdtFCqdjYs2Q2jAPX8c2XQd7Kr/wfV8vwIPs4Ga1ixe5Xrr/YFLTYfKIvWzM6ZtwXZdX7lxXG0L+sxXHcW5t254opRzawQ0S72+dPmjTroIgOP0CQSMt5LDn1T8AAAAASUVORK5CYII=); -} -input.multi-diff[type=checkbox] + label { - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFbSURBVDhPY2xoaGD68+dPMSMjY9L////VgTQjAw4AlH8PxLOPHj1azWxjY1MBVNsBFBfBpwkEgNKcQGwtJyfHyALkF4IE34gqM9zU9WT4wicG4mIA1l/fGIyOL2EQeP8EZEAiC5AQBUlcMQ5ieMXIwfDo9SeG73/+gRXDAAsTI4Pd9wdgTVAgw/Tv3z8GEP7Jwctw78M3DE0goPr6BoPludVgdTAM1wgCv//9B9PIQOPNDYaAGxtRNIEw03+gYhDGBtSBNgVc3wiWR8dM//4DTQBidKD++jqD//X1YDlsGMWpMKD26jqD79V1GM5DxihOZQWGntqrawy+V9ZiOA0dw21k/f6JwerzHQbvS2swTMeGGfPz8l8BLRP9KizDwP0WHk+EwGum/3//94M8y/nmEdZAwIb//vs7g/nk6ZPHzE3NvwITrxLDfwYhIAamZpz4PcM/hslXrl6pBwAmfz5iaAlAuAAAAABJRU5ErkJggg==); -} -input.multi-diff[type=checkbox] + label:hover { - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFPSURBVDhPjZJBSwJBHMXfrG6rWEkl1MFDGOihDn2JIIrqc3QJunbyFhUkRieD+hYepWteuxctXiJ1Q5xmdmZ3bWZTUHezfvAu/3lv3n+HRblcTrbb7fN+v/8eBMFgFpxz13Gcu3q9bqHb7V4M5/9GhatE3cIsy0o99YBKC3jliCWbBK43gK0MoDI9otfTB/vPBC9Uwu4xMC8IzSOSBsFxIYNqMTGcAIYQAlodD3j5/IqENIc5gqt1P/SNZKhaXR0a5E/5BEcrwH1xEHrGZbiuC604DpZ81AoiPJ/WROM4e4sSt3kaaRopNrg7z1FZdSLmcU2saqrX20lTXC5/RFabFmk2m+GLnBnbWJMOThJv4SV/QRqNBjNNM9UiGeQHdDiejZSSG5TSG71zjnVivyVOKlNLlEqlx+xCds7zvU31G6Z938dvEq4QjLMH27ZPvwHFVYQr3h7uHwAAAABJRU5ErkJggg==); -} - -.rgb.fstuple .color-picker.multi-diff:after { - width: 20px; - height: 20px; - content: ' '; - background: darkgray; - display: flex; - clip-path: polygon(0 0, 0 100%, 100% 100%); -} - -.icon-input input { - position: relative; - padding-left: 36px; -} -.icon-input span { - position: absolute; - left: 6px; - top: -2px; - font-family: HiFi-Glyphs; - font-size: 30px; - color: #afafaf; -} -.icon-input input:focus + span { - color: #ffffff; -} - -.icon { - font-family: HiFi-Glyphs; - color: white; -} - -#property-type-icon { - font-size: 50px; -} - -.selectable { - -webkit-touch-callout: text; - -webkit-user-select: text; - -khtml-user-select: text; - -moz-user-select: text; - -ms-user-select: text; - user-select: text; - cursor: text; -} - -.color-box { - display: inline-block; - width: 15pt; - height: 15pt; - border: 0.75pt solid black; - margin: 1.5pt; - cursor: pointer; -} - -.color-box.highlight { - width: 13.5pt; - height: 13.5pt; - border: 1.5pt solid black; -} - -#properties-list { - display: flex; - flex-direction: column; - - margin-top: 16px; -} - -#properties-list .fieldset { - position: relative; - /* 0.1px on the top is to prevent margin collapsing between this and it's first child */ - margin: 0 -21px 21px -21px; - padding: 0.1px 21px 0 21px; - border: none; - border-top: 1px rgb(90,90,90) solid; - box-shadow: 0 -1px 0 rgb(37,37,37); -} - -#properties-list .fieldset.fstuple, #properties-list .fieldset.fsrow { - margin-top: 21px; - border: none; - box-shadow: none; -} - -#properties-list > .fieldset[data-collapsed="true"] + .fieldset { - margin-top: 0; -} - -#properties-list > .fieldset[data-collapsed="true"] > *:not(div.legend) { - display: none !important; -} - -.section-header { - padding: 0 16px; - border-top: 1px rgb(90,90,90) solid; - box-shadow: 1px -1px 0 rgb(37,37,37); - border-bottom: 1px solid rgb(37, 37, 37); -} - -div.section-header, hr { - display: flex; - flex-flow: row nowrap; - padding: 10px 16px; - font-family: Raleway-Regular; - font-size: 12px; - color: #afafaf; - height: 28px; - text-transform: uppercase; - outline: none; - margin-bottom: 10px; - align-items: center; -} - -.section.minor { - margin: 0 21px; - box-shadow: 1px -1px 0 rgb(37,37,37); - border-left: 1px solid #575757; -} - -.container.property { - padding: 0 16px; -} - -.stretch { - width: 100%; -} - -div.section-header .label { - width: 100%; -} - -.section.minor div.section-header { - border-right: 0; -} - -div.section[collapsed="true"] > .container { - display: none; -} - -div.section[collapsed="true"], div.section[collapsed="true"] > .section-header { - margin-bottom: 0; -} - -.section.major { - margin-bottom: 20px; -} - -.section.minor.last { - margin-bottom: 20px; - border-bottom: 1px solid rgb(37,37,37); -} - -.section-header { - background-color: #373737; -} - - -.section-header span { - font-size: 30px; - font-family: HiFi-Glyphs; -} - -.triple-label { - text-transform: uppercase; - text-align: center; - padding: 6px 0; - cursor: default; -} - -.triple-item { - margin-right: 10px; -} - -.triple-item.rgb.fstuple { - display: block !important; -} - -.section-header[collapsed="true"] { - margin-bottom: -21px; -} - -#properties-list .sub-section-header { - border-top: none; - box-shadow: none; - margin-top: 8px; -} - -.sub-section-header + .property { - margin-top: 0; -} - -hr { - border: none; - padding-top: 2px; -} - -.property { - min-height: 28px; -} - -.property.checkbox { - width: auto; -} - -span.indented { - padding-left: 16px; -} - -.property label, .number label { - display: table-cell; - vertical-align: middle; - font-family: Raleway-SemiBold; - font-size: 14px; -} -.property label .unit, .number label .unit { - margin-left: 8px; - font-family: Raleway-Light; - font-size: 13px; -} - -.property div.legend, .number div.legend { - display: table-cell; - vertical-align: middle; - font-family: Raleway-SemiBold; - font-size: 14px; -} -.property div.legend .unit, .number div.legend .unit { - margin-left: 8px; - font-family: Raleway-Light; - font-size: 13px; -} - -.value { - display: block; - min-height: 18px; -} -.value label { - display: inline-block; - vertical-align: top; -} -.value div.legend { - display: inline-block; - vertical-align: top; - width: 48px; -} -.value span { - font-size: 15px; - margin-right: 4px; -} - -#placeholder-property-type { - display: flex; - align-items: center; - width: auto; - margin-right: 20px; -} - -#placeholder-property-locked { - margin-left: 6px; -} - -.checkbox + .checkbox { - margin-top: 0; -} - -.checkbox-sub-props { - margin-top: 18px; -} - -.property .number { - float: left; -} -.property .number + .number { - margin-left: 10px; -} - -.property.range label{ - padding-bottom: 3px; -} -.property.range input[type=number]{ - margin-left: 0.8rem; - width: 5.4rem; - height: 1.8rem; -} - -.dropdown { - position: relative; - margin-bottom: -17px; -} - -.dropdown select { - clear: both; -} - -.dropdown dl { - clear: both; - cursor: pointer; - font-family: FiraSans-SemiBold; - font-size: 15px; - width: 292px; - height: 28px; - padding: 0 28px 0 12px; - color: #afafaf; - background: #575757; - position: relative; - display: flex; - align-items: center; -} - -.dropdown dl[dropped="true"] { - color: #404040; - background: linear-gradient(#afafaf, #afafaf); - z-index: 998; -} - -.dropdown dt { - height: 100%; - box-sizing: border-box; - border-right: 1px solid #121212; - width: 100%; -} -.dropdown dt:hover { - color: #404040; -} -.dropdown dt:focus { - outline: none; -} -.dropdown dt span:first-child { - display: inline-block; - position: relative; - top: 5px; -} -.dropdown dt span:last-child { - font-family: HiFi-Glyphs; - font-size: 42px; - float: right; - margin-right: -48px; - position: relative; - left: -12px; - top: -9px; -} - -.dropdown dd { - position: absolute; - top: 28px; - left: 3px; - display: none; -} -.dropdown dl[dropped="true"] dd { - display: block; -} - -.dropdown li { - list-style-type: none; - padding: 3px 0 1px 12px; - width: 320px; - height: auto; - font-family: FiraSans-SemiBold; - font-size: 15px; - color: #404040; - background-color: #afafaf; - z-index: 999; -} -.dropdown li:hover { - background-color: #00b4ef; -} - -.dropdown dl[disabled="disabled"], .dropdown dl[disabled="disabled"][dropped="true"] { - color: #252525; - background: linear-gradient(#575757 20%, #252525 100%); -} -.dropdown dl[disabled="disabled"] dd { - display: none; -} -.dropdown dl[disabled="disabled"] dt:hover { - color: #252525; -} - -.multiselect-box { - position: absolute; -} -.multiselect-box select { - font-family: FiraSans-SemiBold; - font-size: 15px; - color: #afafaf; - background-color: #252525; - border: none; - text-align-last: center; -} -.over-select { - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; -} -.multiselect-options { - position: absolute; - display: none; - border: none; -} -.multiselect-options span { - font-family: hifi-glyphs; - font-size: 13px; - color: #000000; -} -.multiselect-options label { - z-index: 2; - display: block; - font-family: FiraSans-SemiBold; - font-size: 11px; - color: #000000; - background-color: #afafaf; -} -.multiselect-options label:hover { - background-color: #1e90ff; -} -.multiselect-options input[type=checkbox] + label { - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAYAAAAehFoBAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAB3RJTUUH4goSADUOYnF4LQAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAIMSURBVFjD7ZmxkqowFIZ/7mwJPen1AezV3t6hFvrQhweAHvrQ8wL2xt4HwD7ppd+tvHOvu0gCYdEZTsmAfpNzzpcTcAB84o3iD94sZuCx4+Pxwvl8dl4JcL1ef84lMQPPwBZDSgkp5XsASylBKUUYhhBCvDbw7XYDpRRKKTRNA8YYOOevC5ymKZRS/13jnHdCTwLMOW8tAc45GGNomuY1gKuq6lxFIQQopdMDXy4X5HmudW8URdMCSynBGNOG3Ww20wHf9dVWl4+wbav7a8CMsW9G+Cm22+1T2F8BzvMc1+u18z5CCJIkseNhKSX2+z2qqjLWl84zhBAURQHXde0A31Oa57nWbqSrLwDwPA9FUcD3fTtb82NKu8QOAHVda+srSRJt2E7gtpQKIXA4HH6csmzpyxj4dDo9TalSCpRS1HX9TV86RujSlxGwlBJpmnY+rJRCGIZ/s2BTX9qnZgBwHAee52mJ/l7nx+PRqr6MVtj3fZRlaVRf/5aGDX0Z17DrusiyrHfqhuqrt9aiKEIcx4OBTfU1aOMIggBlWYIQ0utP+uhr8CyxXC5RFIUxdBAE1srKePgxbcbVamWlnAZNa7rNSAhBlmWv8yLlWTPa0Nco83BbM2ZZZsUIowzwj80YxzEWi8VoB4IPGz9yb0YhBHa73agnGGtHJNd1R4ed9FVV33Awf6ebgd8b+Av9A/rq6s3hjgAAAABJRU5ErkJggg=='); - background-size: 11px 11px; - background-position: top 5px left 14px; -} -.multiselect-options input[type=checkbox]:enabled + label:hover { - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAYAAAAehFoBAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAB3RJTUUH4goSADUOYnF4LQAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAIMSURBVFjD7ZmxkqowFIZ/7mwJPen1AezV3t6hFvrQhweAHvrQ8wL2xt4HwD7ppd+tvHOvu0gCYdEZTsmAfpNzzpcTcAB84o3iD94sZuCx4+Pxwvl8dl4JcL1ef84lMQPPwBZDSgkp5XsASylBKUUYhhBCvDbw7XYDpRRKKTRNA8YYOOevC5ymKZRS/13jnHdCTwLMOW8tAc45GGNomuY1gKuq6lxFIQQopdMDXy4X5HmudW8URdMCSynBGNOG3Ww20wHf9dVWl4+wbav7a8CMsW9G+Cm22+1T2F8BzvMc1+u18z5CCJIkseNhKSX2+z2qqjLWl84zhBAURQHXde0A31Oa57nWbqSrLwDwPA9FUcD3fTtb82NKu8QOAHVda+srSRJt2E7gtpQKIXA4HH6csmzpyxj4dDo9TalSCpRS1HX9TV86RujSlxGwlBJpmnY+rJRCGIZ/s2BTX9qnZgBwHAee52mJ/l7nx+PRqr6MVtj3fZRlaVRf/5aGDX0Z17DrusiyrHfqhuqrt9aiKEIcx4OBTfU1aOMIggBlWYIQ0utP+uhr8CyxXC5RFIUxdBAE1srKePgxbcbVamWlnAZNa7rNSAhBlmWv8yLlWTPa0Nco83BbM2ZZZsUIowzwj80YxzEWi8VoB4IPGz9yb0YhBHa73agnGGtHJNd1R4ed9FVV33Awf6ebgd8b+Av9A/rq6s3hjgAAAABJRU5ErkJggg=='); -} -.multiselect-options input[type=checkbox]:checked + label { - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAYAAAAehFoBAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAB3RJTUUH4goSADMveELP9QAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAIqSURBVFjD7ZmxkqowFIb/7GwJPfT6APZib+9QC33o4QGghz70vIC9sfcBsE966bPNWlxnlQTDRWc4JUT4hpPz5SQSAAofFF/4sJiBx47v+wun04m8E+B6vVbzlJiBZ2CLIYRQQgj1EcBCCEUpRRRF4Jyrtwa+Xq+glEJKia7rkKYpGGPqbYHzPFdSyn+uMcZ6oScBZowpzvmje0jTVHVd9x7ATdMoxtjTMZxzUErV5MDn81mVZak1No7jab+wEEKlaaoNGwQBmQz4pq9H8/IeNo5jMmnRpWmKeyP8FZvN5insfwEuy1JdLpfecb7vI8uy3tb2Szelu91ONU1jtP9jjKmmabRgq6qC4zh2VrpbSsuy1FqNdPUFAK7roqoqeJ6ntXH4Mk1pn9gBoG1bbX1lWaYN2wv8KKWcc+z3+z+7LFv6MgY+Ho9PUyqlBKUUbduqe33pGKFPX0bAQgiV53nvj6WUiKIIt2K0qS/tXTMAEELguq6W6H/nOQ6Hg1V9GX1hz/NIXdckCALtB7Vta1VfxnPYcRwURUEeNSGmYaqvwVqL45gkSfIysKm+Xlo4wjAkdV3D9/1BLxmir5d7ieVySaqqMoYOw3CwEV5ufkyLcbVaIUkSq2d1xt2abjH6vo+iKKwfLA5uL58Vow19jdIPPyrGoiisGGGUBv6+GJMkwWKxGO2M+dvGQ36LEZxztd1uRz0Qt7ZFchwHY8NOelQ1NAjm/+lm4M8G/gH2zx33BSr7jAAAAABJRU5ErkJggg=='); -} -.multiselect-options input[type=checkbox]:checked + label:hover { - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAYAAAAehFoBAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAB3RJTUUH4goSADMveELP9QAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAIqSURBVFjD7ZmxkqowFIb/7GwJPfT6APZib+9QC33o4QGghz70vIC9sfcBsE966bPNWlxnlQTDRWc4JUT4hpPz5SQSAAofFF/4sJiBx47v+wun04m8E+B6vVbzlJiBZ2CLIYRQQgj1EcBCCEUpRRRF4Jyrtwa+Xq+glEJKia7rkKYpGGPqbYHzPFdSyn+uMcZ6oScBZowpzvmje0jTVHVd9x7ATdMoxtjTMZxzUErV5MDn81mVZak1No7jab+wEEKlaaoNGwQBmQz4pq9H8/IeNo5jMmnRpWmKeyP8FZvN5insfwEuy1JdLpfecb7vI8uy3tb2Szelu91ONU1jtP9jjKmmabRgq6qC4zh2VrpbSsuy1FqNdPUFAK7roqoqeJ6ntXH4Mk1pn9gBoG1bbX1lWaYN2wv8KKWcc+z3+z+7LFv6MgY+Ho9PUyqlBKUUbduqe33pGKFPX0bAQgiV53nvj6WUiKIIt2K0qS/tXTMAEELguq6W6H/nOQ6Hg1V9GX1hz/NIXdckCALtB7Vta1VfxnPYcRwURUEeNSGmYaqvwVqL45gkSfIysKm+Xlo4wjAkdV3D9/1BLxmir5d7ieVySaqqMoYOw3CwEV5ufkyLcbVaIUkSq2d1xt2abjH6vo+iKKwfLA5uL58Vow19jdIPPyrGoiisGGGUBv6+GJMkwWKxGO2M+dvGQ36LEZxztd1uRz0Qt7ZFchwHY8NOelQ1NAjm/+lm4M8G/gH2zx33BSr7jAAAAABJRU5ErkJggg=='); -} - -.dynamic-multiselect { - position: relative; - top: 6px; - padding-bottom: 6px; -} - -div.refresh { - box-sizing: border-box; - padding-right: 44px; -} -div.refresh input[type="button"] { - float: right; - margin-right: -44px; - position: relative; - left: 10px; -} - -.color-picker { - box-sizing: border-box; - width: 26px; - height: 26px; - border: 3px solid #2B2B2B; - cursor: pointer; -} -.color-picker:focus { - outline: none; -} -.color-picker[active="true"] { - border-color: #000; -} - -.color-picker[disabled="disabled"] { - border-color: #afafaf; -} - -.colpick { - z-index: 3; -} -.colpick[disabled="disabled"] { - display: none !important; -} - -.rgb label { - float: left; - margin-top: 10px; - margin-left: 21px; -} -.rgb label + * { - clear: both; -} - -.rgb div.legend { - float: left; - margin-top: 10px; - margin-left: 21px; -} -.rgb div.legend + * { - clear: both; -} - -.draggable-number-container { - flex: 0 1 124px; -} -.draggable-number { - position: relative; - height: 28px; - flex: 0 1 124px; - display: flex; - align-items: center; -} - -.draggable-number .text { - position: absolute; - display: inline-block; - color: #afafaf; - background-color: #252525; - font-family: FiraSans-SemiBold; - font-size: 15px; - margin: 0; - padding: 0 16px; - height: 28px; - width: 100%; - line-height: 2; - box-sizing: border-box; - z-index: 1; -} -.draggable-number .text:hover { - cursor: ew-resize; -} -.draggable-number .left-arrow, .draggable-number .right-arrow { - position: absolute; - display: inline-block; - font-family: HiFi-Glyphs; - font-size: 20px; - z-index: 2; -} -.draggable-number span:hover { - cursor: default; -} -.draggable-number .left-arrow { - top: 3px; - left: 0; - transform: rotate(180deg); -} -.draggable-number .right-arrow { - top: 3px; - right: 0; -} -.draggable-number input[type=number] { - position: absolute; - right: 0; - width: 100%; -} -.draggable-number input[type=button] { - position: absolute; - top: 0; -} -.draggable-number input::-webkit-inner-spin-button { - -webkit-appearance: none; - visibility: hidden; -} -.draggable-number.fstuple { - height: 28px; - width: 124px; - left: 12px; -} -.draggable-number.fstuple + .draggable-number.fstuple { - margin-left: 28px; -} -.draggable-number.fstuple input { - right: -10px; -} -.draggable-number.fstuple .sublabel { - position: absolute; - top: 6px; - left: -16px; - font-family: FiraSans-SemiBold; - font-size: 15px; -} - -.rect .rect-row { - margin-bottom: 8px; -} - -.row .property { - width: auto; - display: inline-block; - margin-right: 6px; -} -.row .property:last-child { - margin-right: 0; -} -.row .property input { - clear: both; - float: left; -} - -.property.texture { - display: block; -} -.property.texture input { - margin: 0.4rem 0; -} -.texture-image img { - padding: 0; - margin: 0; - width: 100%; - height: 100%; - display: none; -} -.texture-image { - display: block; - position: relative; - background-repeat: no-repeat; - background-position: center; - background-size: 100% 100%; - margin-top: 0.4rem; - height:128px; - width: 128px; - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAABhNJREFUeNrsnVFy4joQRVsSCwAqBMwqsrRsIavMEkICoeAf2+8j1R5ZGDBgpLzoUDVVmTT2dc8It/paOpi3t7faOSciImVZyn6/l6qqRETEWivj8VistYPFd7ud1HUtIiLGGBmPx5JKX0RkMplIzvmPnHNijBERaS7Ef1lrB40bY1oXgH5a/ZH+8P7+LlVVycfHR/MGa60URdGcYOi4MUaKomhGaGx9EZHlcplMP2X+Ly8vPwOgLEtxzklVVVJVVfOznqAsy9YFXhuvqqq5AF/Lj+srtr7+LpV+yvz1mNF+vxcRkdVqJdZaeXp6ap1ws9m0TjibzVoj6lJ8vV6fjJdlKev1ujViU+j7t8tc8p9Op1KWpYw06L9JL0Av0r9l+jXl3nhd11JV1VE8tn5YM3PI3xjzoxVOGvyDU7zQj6s/0tGmI++amtNV087F9Wf/FnVPzRtCXz8RdV1nlb/efUbaJy4Wi0FqzjU1yRgjs9ls0Jp3jb6IyPPzczL9lPkvFot/dwCtB/om/x9oyJoXxps65NW8mPpdNTeX/JtBEtYE/+AUL/Tj6g/qA3TVnD41a6g++Bp9rYOp9FPnH80HOBcvy1I2m81D++BL+o/2AX5r/vgA+AD4AOif8AH8EdpVcy71sX3jWp/8W2AKff/TkUv+Oufr9AF0YuKc66xJ18T7eNP3nP9WfZ0EzufzJPqp8y+KQuq67vYBdETqCDpVU/rEw5oUnr+rD46h73/qUuinzh8fAP22D6AjxznXcqq6akrf+KmaFB6vf4+t7/sAelfIJf/GB9jtdmKMkdVq1dQM3zg4VVNU/NY+1Bgjh8Oh6YM1+dj6X19fzXwgp/wbH0DFtS7oyf0RdKqmhPFr+1RdseKfP7a+Px/IKX98APTbPoDOJrv60L417d54TH3V8lfS5pT/yfUA6/X6qOZcqkm3xrUm6X9CTH3fB0ihnzr/Ix9A/3T1qbfWpGvjMfX9T0UK/dT54wOg/88H8EfGPTVr6D740frhLDmn/Hv5AH1qku9t31KTzh3/aP1LPsBfzr+XDxCO0K6ack/N6qp5MfUv+QB/Of/ePsCQfWmfc6EfV3/kjzZrrRwOh9YtKHSm/LjOH3yrMTzej4c1y//51PHoP0a/tR7AOSdFURw9rz5VU049zw7jl2qWrosP++BY+iI/+wJS6afMv9kXoA6gvimsieHzZr/m6MTp3PPuc3G9SP95OPpx9JtOgT4cHwA+QCJ9+ADwAeADsC+AfQHo/4b1APAB4APAB4APAB8APgB9OD4AfAD4AFFqEnwA+AD4APgA6P86HwA+AHyAZhIBHwA+AHwA+AD04X/eB4APAB8APgB8APgA8AHow/P0AeADwAeADwAfAD4AfAD68Px8APgA8AHgA8AHgA8AH0DO70/v6lHvjaOfVn8U/iLcXx5OUML96X49vRTX3/nPw9FPo9+sB5hMJuKck+VyeVRTrLWtdfNdcf95eldNCuOfn5+tSYy/Pz+2voi0fICc8p/P5z93gJAPEN4+wufN4evaePj99eH+ePTj6p/1Abp60kt9Ksf/v46HDwAfAD6A/6gUPgD7AtgXwPP4DNcDwAeADwAfAD4AfAD4ADyPz289AHyA+Pqp84cPIPAB8AHwAfAB8AHgA7Q+HfAB4APAB4APAB+APjw3HwA+AHwA+ADwAeADwAegD8/TB4APAB8APgB8APgA8AHow/PzAeADwAeADwAfAD4AfACJ//316KfVH/mjLeb31+vx/kWhH0+/tR7AOSdFUUT9/nq9oK4+OJa+iLT25+eUf7MvIOQDxPr+en2F++PRj6PfdAr04fgA8AES6cMHgA8AH4B9AewLQP83rAeADwAfAD4AfAD4APAB6MPxAeADwAeIUpPgA8AHwAfAB0D/1/kA8AHgAzSTCPgA8AHgA8AHoA//8z4AfAD4APAB4APAB4APQB+epw8AHwA+AHwA+ADwAeAD0Ifn5wPAB4APAB8APgB8gBz5AOb19bX2TYLpdNpqQ7bbbctJGjJeVZVst9vWLSu2/vf3t+Sc/yicFIRr0C7Fu76f/lw8XBePflr9/wYAqWwWUSLcO54AAAAASUVORK5CYII='); -} -.texture-image.no-texture { - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAB81JREFUeNrsnTGPm0oXht97FWm2Ch2pTEeHpUihsyvTuXO67Ta/IPkr+Qfp3MWdO7Zad0SKZDo6XIWOrTzV9xVXZ8SygGHXG4/t96lW68GGw8vMmZlzDv98+/btfyBXy780wXXzTv74/fs3rXFFfPz4kT0AoQAoAJqAAiAUAKEACAVAKABCARAKgFAAhAIgFAChAAgFQCgAQgEQCoBQAIQCIBQAoQAIBUAoAHLmvDv3C7i7u4PjOMiyDOv1+mC75XKJoiga2wRBAN/34TgOHMdBWZYoigJpmiLPcwrARhzHAQD4vg/P81pvlLRrwvM8zGYz00ZrbY5xHAe+7yPPc9zf36MsSwrAVmazGX78+DHoGM/zsFgsAAB5nmOz2ZgeQimF8XiMMAxNu+VyaQRCH8Ai8jyH4zgIw7D3MUopzOdzAECaplitVk+GB601kiTBz58/obWG4ziIoohOoI38+vULABCGYWd3X2U6nUIphbIsEcdxa7uiKPDw8GCGGtd1KQDbKMsSWZZBKYXJZNLrGN/3zdN/iDRNTdcvx1EAFqGUwmazeeIQduG6LpRSAIAsy3r9hrRjD2BxL5AkiXEI+8wetNa9PXtp13eIoQBOQJIkxmHrcgjlJkov8JKpJwVgIVpr47CFYdh6g/f7/ZM5/9CehgKwmDRNURQFlFKYTqeNN/rx8dH0AH2faBn7KYAzQKZ1QRCYZd0qf/78MX+PRqNe3ymO5W63owBsR9bwZShoGirEq++zeBQEweBZAwVwYh4eHqC1RhAErQ6jOHVdK3yu65qhJE1TDgHn5BDKTW6auxdFYdYOgiDAYrF40k4phTAM8fnzZyilUBRF54rhOfIOF06SJMYPaPt8v99jOp3C8zx4nget9bPZQ5ZlF3fzL0IAZVke9OLv7+/Njl/brCHLMozHY4xGI3z48MH0EEVRIMuyi40H+EdqBbNS6HXBSqGEAiAUAAVAE1AAhAIgFAChAAgFQCgAQgGQq+Eom0GLxeJgGHYVSdCUhM02yrI0qV5hGGIymaAsy9b0LNd1cXt7CwDYbDa98wOA/zKLVquVSQGr/nYTbe2iKDIh53JtZVmiLEvsdjtst9tn5z7EDmfXA3QFXdaTMbvYbrdm568tgkdueJ7njbt3QwJA+8YJ1tsFQQDXdXFzc2N2E0Uwk8kEX758eXbMEDtY2QOsVqtn//v69SsAYL1eH9xK7dNGgjuiKMJ4PH4WmSN7+QBMFu/3798bn1oAzz47NvVrqmYgz2azRpv1scNV+wDVaN969y6JIEmSWBmyJenlIgZbcgvOzgmUqJxqkmY18ldCvGwkz/MntQcogBcgETrVMV98Aptvfh1JTKEAXsBms4HWGp7nYT6fw3Ec5Hlufbi253lQSkFr3VqmhgLoQVmW2G63ZigQx8/2my/FKCR17WLWAV7LfD5vzOFLkqS1W0/T1HT9RVFY5/jNZjMz3ouvorVGHMet9QheYoer7AGq478Y2LaiDTc3N3Bd90megSwG2YQVPcDQ+a/ccK01ttutWSWsetl/i7bfq16TzP1lGFgul0exw9X2AJLGJV3joRXCl3rnXbUDhmQKl2WJ9XoNrbV1vdXZCUCWWqvVQGR8HFIgqmuaKUiCSJcA+nrzWmvzdA/ZN6EAKlTz/eXmA3iSuXOoNEzfBRsA+PTpU+PnUjxSfnvo9/ZNR6cAakjFj2rqd3VtQJ6u1z5h1e+SdYbqdK5aWHLImC0OoFQgpRN4YPoD/LfRVC8C2TQlkhVC3/dfVDG0/l1xHCOKIvi+b572atJoURSdtYnbfAHxV0aj0TP/oY8dzqYH6OscHXK26tO+rqcujmNTIKqtJkDfc0vTFMvl8smu436/R57niOO4NSbh0HfLkFHtpYbY4dgwOfRKYXIooQAIBUAB0AQUAKEACAVAKABCARAKgFAA5Gp4s93AKIrw/v17ExsnFEWB/X6P3W6HLMtaN0+GJkwOad+W2FlPLq3GHFSRdq85h2PYyGoByG6cvJOnHiEryZJSg7e+s1ZNmOyzSza0ffWYJsIwbMzk7Tp+6Dm81kZWC0BoCnSU7dowDE2K12q1alT60EDJYwVWKqUQRdHgPf9jnfMQG52dDyA5fLKnLlGztiB5Bn1eP3fuNvr31IaWZM9jhHIdEwk5G1Jk4hxtdPJZQJZlJrLWlnBpx3FMmrnrup3RReduIyumgXJxtryRUxw4mQXIO4Yv0UZWCMDWN3I2vX7u0mxk1RtDmp6yoQmTbe27kjK7iOMYt7e3CIIA2+22VyLIWyZ5Hrsnsmol0Jac+fo51QtSXJKNrOgBuvLsTrUOUO8FxAP3ff/gTXiLc3irt5aevAdQSpmpja0vZqq+fm4ymfz18i5vaaOTC0DSvapv8rQRmRY6joPxeHwxNjqpAGSpUwx8ikKJQ5AyNFKb4BJsdBIfwPM8BEFgFjXSNG3debMJSUv7GyuWf8tGby6Aaq2c+qvaJce/a3p2ioTJQ73A3d3di6aBbef8WhtZKQDJ6K1fTJ7neHx8PFjWTcbbvvPePm8QbVtc6ft/+UwKUdfbDT3n19roGDA59EphciihAAgFQAHQBBQAoQAIBUAoAEIBEAqAUACEAiAUAKEACAVAKABCARAKgFAAhAIgFAChAAgFQC4CkxgiceKEPQC5Iv4/APgB2O7x8IXXAAAAAElFTkSuQmCC'); -} -.texture-image.no-preview { - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAIAAABMXPacAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAA8sSURBVHhe7Z3rbxXFG8d7B9SWthRabLmIYlHkIEXKJdXYBEXxHtEXprwxxsR3/jG+8PLCaDDGeAkmKsTEoCUVKoVCA6WNtLS2UEUKBSy0tKW/D+eZM9nu7tmz55z+mC2Zz4tl9tk5c2bnO/PMM2dnS+6nn36aYzFH7vvvv6+SFhMoAY4fPy7nljvG448/zjFPTiymsAIYxgpgGCuAYawAhrECGMYKYBgrgGGsAIaxAhjGCmAYK4BhrACGsQIYxgpgGCuAYawAhrECGMYKYBgrgGGsAIaxAhjmLhQgPz+/pKRk3rx56jzaRHFf0ObNmxctWkTi7Nmzp0+fFqNm+/btRUVFP/30kzp3UFtbu27duqVLl+bl3e5Y169f7+rqam1tvXnzpmSIFNHdF1RTU7M6TkNDQ0FBgbImWLVqFZfUSQKyvfzyy88991x1dfXU1NSFCxdGRkbuueeeurq6pqam0tJSlS96RNcFSQvSo9V5IC+88MIDDzwwOjr6448/fvTRR19++eVnn322Z8+ev//+u7i4+M0331ywYIHKGjGiK8Aff/zBMRaL5ebmiiUZjz322MqVK/Ez33333ZkzZxgBYh8eHt67d++lS5do/W3btokxakRXANxIf38/3mPNmjXKlARxpkeOHKGtxaIZHx9vaWkhwfTg9WZRILoCgIQG0r7JKC8vlxm7s7NTLC6YyW/cuFFYWIiPUqYoEWkB+vr6cOJLlizBwyiTB2l9vA0xj1hcTE9PDw4OkiA6EkukiLQAcOzYMY4bN26UUy8LFy7k+O+//8qpL1euXOF43333yWmkiLoATKqEQwSmlZWVyjQTIiWOwZG+npYjSNQFwIG0tbWRqK+vF4sL1r0qlZzJyUmOYXLeeaIuAHR3d+PfmQbE27hgguUY3LgS/0RzHMwBAei/R48ezcvL8x0EOCiOxEJy6osoJ1JFjTkgAHR0dExMTBDLexe0EvsTKQUMgsWLF3OUWChqzA0BGARoQBN7wyHWa6Ojo1x6+OGHlWkmaEOoeuvWrXPnzilTlJgbAgBeiEEQi8W8Pf3kyZMct27d6v0JGsf15JNPkmA5lmyhYJY5IwAenNmYBW1RUZEyJSBMYiYoLi7etWtXWVmZsubkkHPHjh2EsCjX3NysrBFjzggANDSeRJ04wEF9//33rLYqKip27979yiuvNDY2Pvvss2+//TZ+ieBn//79V69eVbkjRv6WLVv4hxW/nEcB+iyuo6ura3x8XJnicIqToV8zGpgSlDXO2NhYZ2cnV+WnIVZtTLxEn+fPn9+3b180p9+qqiqOd9ub8ihH67M8xuPT65mf1YXocXe+KY+PGhoa6unp4Rjl1tfcbQLMOawAhrECGMYKYBgrgGGsAIaxAhjGCmAYK4BhrACGyfy3oNdff72mpkadJLh27Vpvb29LS8vExIRYdu7c6dpLOz09ffPmTXLypadOnVLWnJzGxsZYLKZOPHR0dDQ3N7/33nv5+fkff/yx7/PFBQsWvPPOO5T/4YcfLly4sKmpaXBw8Ntvv5Wr7777bsAOUbINDw+Th5IpX1kTyGcPHz7c2tqqTHG4NW7wzz//9N2tHczs/BY0NjZ2PQFVLy4uXr9+/UsvvaQuJxgfH1eZ4tkKCwsrKiq2b9/u3XbozOkEzaamps6ePUueZHvcsOfl5ZFHtkH4oorzQOFU7MqVKzS0S6fy8nKxeDvckiVLOGbza2u22yW/+eYbOo46ie9Te/XVV5ctW7Z8+fK//vpLWXNyfvjhB2ctaaaGhoYNGzZs3bq1q6tLWeP88ssvdCh14oFLDz30EA3tuxFRhBGRkvHJJ5+olB8XLlxg6NCs/f39ypRo93/++Wfp0qWMP+fuCnna7N2TGp5ZngMQ48iRIyQefPBBsfhy69atgwcPjo6OlpSU+G42SQaicv80tPfBJBbslBwsQDBDQ0McpVk1CMBAx2HyFa79jUhFfeRTmTH7k7DsEky5DxBPffHiRRKytS0kNMTAwAAN4d0tigX7+fPnfaeHkEjlxbFoEIAvlTFRXV0tRhBnNTIy4hwT6TL7Asgz2zBvBUlO/K+chkQc1IoVK+RUI5YzZ87IaWZIX3buMpIJAP+Jroxv5zQgOmW52WL2BZDtyv/995+cJkMeHHJX6T42wcPgZ5gJ1HkCsWTjf4C+TCuXlpZqFyctLl6etpZpIH5F6eScAjNglgVg+n3iiSdIuHoiI/f2S19xamtrN23a9NprrzEVt7W1uSKWtWvXPu2HuhzfHkF/pFfef//9ypSTQxoLPi3lw3dV3Ez4UnU5/nicJpZuBAigvTzfyyU9DWQfAkG2UdCLL76oPeC99947f/58Et3d3cQMYhTk0b8TejGhfXt7uzpPgCfxuhf49ddfVSonp6enhyhr1apVeHyxkOYYxv8QJauUA9yaXpEQCKEH8zAJThGA1pd7lLamM0mCPNhl73vGZDsCGK10FgGffvnyZZYqP//8s7qcgCY7EUemMvz+F198ceDAAaZiyaA5duwYixov6nIcaWhpdEHSfIucBqCKm4m8hSDIBhHp3URoMgHEr9wefHoaYChw71qbjMlWgK+//pp1o/DBBx98/vnnLBfp3epyAmI4ujDs3bv3t99+I/J5/vnnfd++4/7pj17U5TjohzsuKysTL8yRNM5HwqpgVHEzce7KoYlpUynZO83qaYAOxzGbFYCQrQAsXOkXgrc7+4IYuA5WwgHvvaSEVuMoKy859vb23r6QNbQ+zof2Je2cAAQ9DYhCWU4AMPtRUBhko2B9fX1aiwAnEu3IakCOYfxPSFgN4HnwP7h7xHA6GT0NyFScZQgEZgRgimYyKCwsrKurU6Y0weHIbwO0FEfGX5bxuBPp8kR0jAPX22d8EY2Oa6qqqiJt3gVlzKFDhzjGYjFaUCzpgs/BGzQ2NnJkWg7pAMMg8Y/8Wul1Mn19fUiONtl3fzAmAP0XN8IgcM0EGzZs2JkElSOBTAMsLDiGnwBUWR74XpUjvuxiJS/TgK8AdBpUz34CAGMCgPy27hoEdC5Zr3lRORIQ8krYMzExMTAwIMaUqLI8iE/XyCCgj+NnxKLRoWf2/gcyfyBDGDNv3jw6csCP70C0QPvSUq6tzgKelK5EUxJZElazlFMX/PB6efkIJXsD0IKCgsrKSuclmpi1t6S9uBy6lJzMy1My5ae892DExdn/R8wYd+fu6DmHFcAwVgDDWAEMYwUwjBXAMFYAw1gBDGMFMIwVwDBp/xSxZs2aqqqqsbGxw4cPK1PiD2W0t7cne0K9ePHitWvXXr9+Xf4aKFRWVj7yyCMkKIfSxKgpLS1lpT4yMqIrxinGU6dOBf95OGH16tXV1dWuSmrkmbs6iTM5OXnjxo2enh7560Oap+O7MZz7AVzIF6kTPwI+m+FPEbT1+vXrN2/eXFJSokzxfXAYH330UXXuYd26dWRw/uoZi8WwgPPZukYKdO5vJI0FDdR5IL6V1KxYseL2FzvYuHFjQ0NDU1OTa7uRXFUnftTU1EieZKh8yUlPALott3T58mXSiC9GkJ/mA/aDyo1JNsjPz6fdr169OjU15SxnVqioqCgrK/NW0oXefrF///4DBw5QN2r1zDPPFBcXqxyhOXnypBTlReVITnoCyP20tLS4Gq6/v58hvGjRIudfi9HIrqnR0VG9jWfZsmXz58/nnoeGhiQt9llBVxIXFCCA3n7R3d3d0dFBY3EXRUVF4hjTAq8oRXlROZKTtgATExN9fX0DAwMyGsQ+PT0te3V8b1iMztqIpbe3l6JkNIh9VtCVpEGdlUyJPOjnI3J6Z0hDALkZbozuL63pbG6vReMSQFqcEcOACPhUZoj/kUrKPonwhcvTlTDbimeRNASQt1mkp9N5uUPn+y2Dg4M4Ge7f1eOQTR4taf+zcuVKfI6UI5sbli9f7pyfs0GaWwpnmLoqGYxswwr/dHNWSEMA7o37kfdecK+4b+luchUv5NudnS0iiEU/Rmfg5+XlBb/QEZ7gSjoh0CpPwOy1adMmQrVz58653tgJAz1MFTQT79+w8xJWACZSvobeoWN2r9MXAWSfmkb8u8v/UIjuaOk6igCkrYMrqXnqqad2JyAA3bZtG8N037593n2VKamvr1cFzaS2tlblSE5YAeQenLvPpJc57w0ng0thYaL3u0mLcGN6Bwf+p7CwkOmRfiqWixcv4rsIqLP3QmEqqRkeHqZWQK8njMH1U+233nor5FLDCcs3KcpFypckIOz2dLkHhiqrG7EAlZYmlqAb6Oksaoj65W+6iWOhG+pdU1IOGjjLQSGGF5nlD1BmTMhKCq2trXpcAkOT5RuV37Fjx1dffaWs4Whvb3f9DbvwhBoBdE8aiASr5y0O5B0j519MlVvSDt21/iooKBCPxFEVEYcGwhhmwAYgrUwiZSV9YUQeOnQI31VVVZXWe4NZEkoAqT3tyIrRibwQ6Ww4Qho6mvgTmoNG4ZZ0/EO70/cZ7+rzDojc+VTGe3VBur+3kvq/MInnCgINqD+JDLxQxqQWIDc3VzoyHYSB5uT333/HfUtDS2agCYhqWN8CpxKwyiVpI/XhmUhQJBkyQz7rrWRbWxvu3lXJZMhw0RW+A6QWQLoz9+DyoYI3hmFlzxHN+CAJp/+RAMk5SWqyjIXE/ySrJOsyjikLp+OzaiEKohxl+v+TWgCpt2+rgTfOu3TpEoENrQ/OcBP/w0RHyMGUKxYnrAbod84IyheCa/K4YH4KrqSvAK6i6urq3njjDcbu6dOnXTVUOWZCf1KX48opqweZOwNIEQVp/6PXTS7w77SyDHC9C5NeT0RBorOz0+V/5PcWL5OTk0hFkEq2EydOKKsHJlWVcoCjl8KTVVJUd1XStyjmp4MHD6qTBLt27VIpB3v27NEDZUMcSbugbrhBdeJHij9dTDyAvFQrWaMQXyLS+Pj4tWvX9PAn/kV5hgJhJXYxMgLIQDm+u3SBeZgOKJM2/YuhwJSoN+SWlJTQiJTphTZlzRlQSXBWkjUwsan6cBy+iLD9+PHjzc3Nzv22RLQqhwfEphBukx6mTH6wEEn2kOru/NPFc4gMn4hZZhcrgGGsAIaxAhjGCmAYK4BhrACGsQIYxgpgGCuAYawAhrECGMYKYBgrgGGsAIaxAhjGCmAYK4BhrACGsQIYxgpgGCuAYdS2FIsp7AgwSk7O/wCqCi/+JioQYgAAAABJRU5ErkJggg=='); -} - -.two-column { - display: table; - width: 100%; -} -.two-column > div { - display: table-cell; - width: 50%; -} - -#properties-list .fieldset .two-column { - padding-top: 10px; - display: flex; -} - -#properties-list .two-column .fieldset { - width: 50%; - margin: 0; - padding: 0; - border-top: none; - box-shadow: none; -} - -#properties-list .two-column .column { - position: relative; - top: -10px; -} - -#properties-list .two-column .fieldset div.legend { - width: 100%; - margin: 21px -21px 0 -21px; - padding: 16px 0 0 21px; - font-family: Raleway-Regular; - font-size: 12px; - color: #afafaf; - height: 10px; - text-transform: uppercase; - outline: none; -} - -#properties-list .two-column + .property { - margin-top: 6px; -} - -.fieldset .checkbox-sub-props { - margin-top: 0; -} - -.fieldset .checkbox-sub-props .property:first-child { - margin-top: 0; -} - -.column { - vertical-align: top; -} - -.indent { - margin-left: 24px; -} - -::-webkit-scrollbar { - width: 20px; - height: 10px; -} -::-webkit-scrollbar-track { - background-color: #2e2e2e; -} -#entity-table-scroll::-webkit-scrollbar-track { - border-bottom-right-radius: 7px; -} - -::-webkit-scrollbar-thumb { - background-color: #696969; - border: 2px solid #2e2e2e; - border-radius: 8px; -} - -/* FIXME: Revisit textarea resizer/corner when move to Qt 5.6 or later: see if can get resizer/corner to always be visible and -have correct background color with and without scrollbars. */ -textarea:enabled::-webkit-resizer { - background-size: 10px 10px; - background: #252525 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAIAAAACUFjqAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAXSURBVChTY1RVVWXADZigNA4wMqUZGACS3gCD5UUtKAAAAABJRU5ErkJggg==) no-repeat bottom right; -} -textarea:focus::-webkit-resizer { - background-size: 10px 10px; - background: #000000 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACOSURBVChThdC5DQQhDAXQvyRI5LQxFdABARWQElAPogYkiqEWQhLYGe8xxzJaS5a/8AuQHwDG2n+Lvee0hBDQWlO+hRvy3mNZFjDG5vCDOOeIMaL3/guPKISAWiu9n+AVSSlhraXdF86Qcw6tNdoTvEOlFOScd6iUOv3JGEMopYQx9jNvaawnoHnNr8Z4AuRLPOq2gPgnAAAAAElFTkSuQmCC) no-repeat bottom right; -} -textarea:enabled[scrolling="true"]::-webkit-resizer { - background-size: 10px 10px; - background: #2e2e2e url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACKSURBVChTjdAxDsMgDAXQT4UYuQIzCwsSKxsSJ4YDoByDY7AwUOG2aZMQqX+xhd9gzIwxA3/k8a7LCCFgraX+Fk4UY4RSCoyxNfwgzjlyzhhjXOEvSimhtUbvB3hGUkp472m2wxUKIaD3TnOCd6jWim3bvlBrfdjJOUeolEJoZj/4PMH83bl/BXgCWSs2Z09IjgoAAAAASUVORK5CYII=) no-repeat bottom right; -} - - -div#grid-section, body#entity-list-body { - padding-bottom: 0; - margin: 16px; -} - -#entity-list-header { - margin-bottom: 36px; -} - -#entity-list-header div { - display: inline-block; - width: 65px; - margin-right: 6px; -} - -#entity-list-header div input:first-child { - margin-right: 0; - float: left; - width: 33px; - border-right: 1px solid #808080; - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} -#entity-list-header div input:last-child { - margin-right: 0; - float: right; - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} - -#delete { - float: right; - margin-right: 0; - background-color: #ff0000; -} - -#entity-list { - position: relative; /* New positioning context. */ -} - -#filter-area { - padding-right: 168px; - padding-bottom: 24px; -} - -#filter-type-multiselect-box select { - border-radius: 14.5px; - width: 107px; - height: 28px; -} -#filter-type-options { - position: absolute; - top: 48px; -} -#filter-type-options div { - position: relative; - height: 22px; -} -#filter-type-options span { - position: relative; - top: 3px; - font-family: HiFi-Glyphs; - font-size: 13px; - color: #000000; - padding-left: 6px; - padding-right: 4px; -} -#filter-type-options label { - position: absolute; - top: -20px; - z-index: 2; - height: 22px; - width: 200px; - padding-top: 1px; -} -#filter-type-options-buttons { - top: -22px; - width: 224px; - z-index: 2; - background-color: #afafaf; - padding-bottom: 6px; -} -#filter-type-options input[type=button] { - position: relative; - left: 16px; - z-index: 3; - height: 23px; - min-width: 60px; - font-size: 10px; - color: #000; - background: linear-gradient(#afafaf 20%, #808080 100%); -} -#filter-type-options input[type=button]:enabled:hover { - background: linear-gradient(#afafaf 20%, #575757 100%); -} - -#filter-search-and-icon { - position: relative; - left: 118px; - width: calc(100% - 126px); -} - -#filter-in-view { - position: absolute; - top: 0; - right: 126px; -} - -#filter-radius-and-unit { - position: relative; - float: right; - margin-right: -168px; - top: -45px; -} -#filter-radius-and-unit label { - margin-left: 2px; -} -#filter-radius-and-unit span { - position: relative; - top: 25px; - right: 9px; - z-index: 2; - font-style: italic; -} -#filter-radius-and-unit input { - width: 120px; - border-radius: 14.5px; - font-style: italic; -} -#filter-radius-and-unit input[type=number]::-webkit-inner-spin-button { - display: none; -} - -#entity-list-footer { - padding-top: 9px; -} - -#footer-text { - float: right; - padding-top: 12px; - padding-right: 22px; -} - -input[type=button]#export { - height: 38px; - width: 180px; -} - -#no-entities { - display: none; - position: absolute; - top: 80px; - padding: 12px; - font-family: FiraSans-SemiBold; - font-size: 15px; - font-style: italic; - color: #afafaf; -} - -#entity-table-columns-multiselect { - position: absolute; - top: 51px; - right: 22px; -} -#entity-table-columns-multiselect-box select { - height: 28px; - width: 20px; - background-color: #1c1c1c; - border-top-right-radius: 7px; -} -#entity-table-columns-options { - position: absolute; - top: 50px; - right: 110px; -} -#entity-table-columns-options div { - position: relative; - height: 22px; -} -#entity-table-columns-options label { - position: absolute; - top: -22px; - height: 22px; - width: 100px; - padding-top: 4px; -} -#entity-table-columns-options input[type=checkbox] + label { - padding-left: 30px; -} - -#entity-table-scroll { - /* Height is set by JavaScript. */ - width: 100%; - overflow-x: hidden; - overflow-y: auto; - box-sizing: border-box; - padding-top: 28px; /* Space for header and footer outside of scroll region. */ - margin-top: 28px; - border-left: 2px solid #575757; - border-right: 2px solid #575757; - border-bottom: 2px solid #575757; - border-bottom-left-radius: 7px; - border-bottom-right-radius: 7px; - background-color: #1c1c1c; -} - -#entity-table-scroll .glyph { - font-family: HiFi-Glyphs; - font-size: 15px; -} - -#entity-table { - margin-top: -28px; - margin-bottom: -18px; - table-layout: fixed; - border: none; - background-color: #1c1c1c; -} - -#entity-table thead tr, #entity-table thead tr th { - background: none; -} - -#entity-table .glyph { - margin: 0 -2px 0 -2px; - vertical-align: middle; -} - -#entity-table thead { - box-sizing: border-box; - border: 2px solid #575757; - border-top-left-radius: 7px; - border-top-right-radius: 7px; - border-bottom: 1px solid #575757; - position: absolute; - top: 49px; - left: 0; - width: 100%; - word-wrap: nowrap; - white-space: nowrap; - overflow: hidden; -} - -#entity-table th { - display: inline-block; - box-sizing: border-box; - padding: 5px 0 0 0; - vertical-align: middle; - overflow: hidden; - text-overflow: ellipsis; -} - -#entity-table th:focus { - outline: none; -} - -#entity-table th .glyph { - position: relative; - left: 4px; -} -#entity-table th .glyph + .sort-order { - position: relative; - left: 4px; -} - -#entity-table thead .sort-order { - display: inline-block; - width: 8px; - margin: -5px 0 -3px 0; - vertical-align: middle; -} - -#entity-table thead .resizer { - position: absolute; - top: 1px; - height: 26px; - width: 10px; - cursor: col-resize; -} - -#entity-table .dragging { - background-color: #b3ecff; -} - -#entity-table td { - box-sizing: border-box; -} -#entity-table td.glyph { - text-align: center; - padding: 0; -} - -#properties-base { - border-top: none !important; - box-shadow: none !important; - margin-bottom: 5px !important; -} - -#properties-base #property-type-icon { - font-family: HiFi-Glyphs; - font-size: 31px; - color: #00b4ef; - margin: -4px 12px -4px -2px; - width: auto; - display: none; -} - -#properties-base #property-type { - padding: 5px 24px 5px 0; - border-right: 1px solid #808080; - width: auto; - display: inline-block; -} - -#properties-base .checkbox label span { - font-family: HiFi-Glyphs; - font-size: 20px; - padding-right: 6px; - vertical-align: top; - position: relative; - top: -4px; -} - -#properties-base input[type=checkbox]:checked + label span { - color: #ffffff; -} - -#id label { - width: 24px; -} -#property-id { - display: inline-block; -} -#property-id::selection { - color: #000000; - background-color: #00b4ef; -} - -input#property-scale-button-rescale { - min-width: 50px; - left: 152px; -} -input#property-scale-button-reset { - margin-right: 0; - left: 250px; -} - -#property-userData-static, -#property-materialData-static { - display: none; - z-index: 99; - position: absolute; - width: 96%; - padding-left: 1%; - margin-top: 5px; - margin-bottom: 10px; - background-color: #2e2e2e; -} - -#property-userData-saved, -#property-materialData-saved { - margin-top: 5px; - font-size: 16px; - display: none; -} - - -#div-property-collisionSoundURL[style*="display: none"] + .property { - margin-top: 0; -} - -.context-menu { - display: none; - position: fixed; - color: #000000; - background-color: #afafaf; - padding: 5px 0 5px 0; - cursor: default; -} -.context-menu li { - list-style-type: none; - padding: 4px 18px 4px 18px; - margin: 0; - white-space: nowrap; -} -.context-menu li:hover { - background-color: #e3e3e3; -} -.context-menu li.separator { - border-top: 1px solid #333333; - margin: 5px 5px; - padding: 0 0; -} -.context-menu li.disabled { - color: #333333; -} -.context-menu li.separator:hover, .context-menu li.disabled:hover { - background-color: #afafaf; -} - -input.rename-entity { - height: 100%; - width: 100%; - border: none; - font-family: FiraSans-SemiBold; - font-size: 15px; - /* need this to show the text cursor when the input field is empty */ - padding-left: 2px; -} - -.create-app-tooltip { - z-index: 100; - position: absolute; - background: #6a6a6a; - border: 1px solid black; - width: 258px; - min-height: 20px; - padding: 5px; - z-index: 100; -} - -.create-app-tooltip .create-app-tooltip-description { - font-size: 12px; - font-style: italic; - color: #ffffff; -} - -.create-app-tooltip .create-app-tooltip-js-attribute { - font-family: Raleway-SemiBold; - font-size: 11px; - color: #000000; - bottom: 0; - margin-top: 5px; -} - -#toggle-space-mode::before { - font-family: HiFi-Glyphs; - font-size: 20px; - text-transform: none; - min-width: 32px; - padding-right: 4px; - vertical-align: middle; -} - -#toggle-space-mode.space-mode-local::before { - content: "m"; -} - -#toggle-space-mode.space-mode-world::before { - content: "\e02c"; -} - -.container { - display: flex; - flex-flow: row nowrap; - margin-bottom: 8px; - min-height: 28px; -} - -.container > label { - margin-top: 6px; - width: 160px; - min-width: 160px; - max-width: 160px; -} - -.container > div.checkbox { - padding-top: 6px; -} - -.container > .value { - width: 100%; -} - -.container .row { - display: flex; - flex-flow: row nowrap; -} - -.container.shrink { - width: min-content; -} - -.fstuple { - display: flex; - flex-flow: row; -} -.fstuple input { - margin-left: 4px; - margin-right: 10px; -} -.fstuple label.red, .fstuple label.x, .fstuple label.w { - color: #C62147; -} -.fstuple label.green, .fstuple label.y, .fstuple label.h { - color: #359D85; -} -.fstuple label.blue, .fstuple label.z { - color: #0093C5; -} - -.xyz.fstuple, .pyr.fstuple { - position: relative; - left: -12px; - min-width: 50px; - width: 100px; -} - -.rgb.fstuple .tuple { - display: none; -} - -input.number-slider { - background: #575757; - border-radius: 4px; - color: white; -} - -.fstuple > div { - display: flex; - align-items: center; - justify-content: left; -} - -.flex-row { - display: flex; - flex-flow: row; -} - -.flex-column { - display: flex; - flex-flow: column; -} - -.flex-center { - align-items: center; -} - -.flex-evenly-spaced { - flex: 1; -} - -#property-serverScripts-status { - font-family: Raleway-Light; - font-size: 14px; - margin: 6px 0; - cursor: default; -} - -#property-name, #property-id { - display: flex; - width: 100%; -} - -.spacemode-hidden { - display: none; -} - -#placeholder-property-type { - min-width: 0; -} - -.collapse-icon { - cursor: pointer; -} - -#property-userData-editor.error { - border: 2px solid red; -} - -#property-userData-editorStatus { - color: white; - background-color: red; - padding: 5px; - display: none; - cursor: pointer; -} - -#property-materialData-editor.error { - border: 2px solid red; -} - -#property-materialData-editorStatus { - color: white; - background-color: red; - padding: 5px; - display: none; - cursor: pointer; -} - -input[type=number].hide-spinner::-webkit-inner-spin-button { - -webkit-appearance: none; - visibility: hidden; -} - -div.jsoneditor-menu a.jsoneditor-poweredBy { - display: none; -} diff --git a/scripts/simplifiedUI/system/html/css/hifi-style.css b/scripts/simplifiedUI/system/html/css/hifi-style.css deleted file mode 100644 index 90a5b366c2..0000000000 --- a/scripts/simplifiedUI/system/html/css/hifi-style.css +++ /dev/null @@ -1,175 +0,0 @@ -/* -// hifi-style.css -// -// Created by Zach Fox on 2017-04-18 -// 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 -*/ - -@font-face { - font-family: Raleway-Regular; - src: url(../../../../resources/fonts/Raleway-Regular.ttf), /* Windows production */ - url(../../../../fonts/Raleway-Regular.ttf), /* OSX production */ - url(../../../../interface/resources/fonts/Raleway-Regular.ttf); /* Development, running script in /HiFi/examples */ -} - -@font-face { - font-family: Raleway-Light; - src: url(../../../../resources/fonts/Raleway-Light.ttf), - url(../../../../fonts/Raleway-Light.ttf), - url(../../../../interface/resources/fonts/Raleway-Light.ttf); -} - -@font-face { - font-family: Raleway-Bold; - src: url(../../../../resources/fonts/Raleway-Bold.ttf), - url(../../../../fonts/Raleway-Bold.ttf), - url(../../../../interface/resources/fonts/Raleway-Bold.ttf); -} - -@font-face { - font-family: Raleway-SemiBold; - src: url(../../../../resources/fonts/Raleway-SemiBold.ttf), - url(../../../../fonts/Raleway-SemiBold.ttf), - url(../../../../interface/resources/fonts/Raleway-SemiBold.ttf); -} - -@font-face { - font-family: FiraSans-SemiBold; - src: url(../../../../resources/fonts/FiraSans-SemiBold.ttf), - url(../../../../fonts/FiraSans-SemiBold.ttf), - url(../../../../interface/resources/fonts/FiraSans-SemiBold.ttf); -} - -@font-face { - font-family: AnonymousPro-Regular; - src: url(../../../../resources/fonts/AnonymousPro-Regular.ttf), - url(../../../../fonts/AnonymousPro-Regular.ttf), - url(../../../../interface/resources/fonts/AnonymousPro-Regular.ttf); -} - -@font-face { - font-family: HiFi-Glyphs; - src: url(../../../../resources/fonts/hifi-glyphs.ttf), - url(../../../../fonts/hifi-glyphs.ttf), - url(../../../../interface/resources/fonts/hifi-glyphs.ttf); -} - -body { - color: #afafaf; - background-color: #404040; - font-family: Raleway-Regular; - font-size: 15px; - - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - - overflow-x: hidden; - overflow-y: auto; -} - -hr { - border: none; - background: #404040 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAYAAACp8Z5+AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAAjSURBVBhXY1RVVf3PgARYjIyMoEwIYHRwcEBRwQSloYCBAQCwjgPMiI7W2QAAAABJRU5ErkJggg==) repeat-x top left; - padding: 1px; - -webkit-margin-before: 0; - -webkit-margin-after: 0; - -webkit-margin-start: 0; - -webkit-margin-end: 0; - width: 100%; - position: absolute; -} - -.hifi-glyph { - font-family: HiFi-Glyphs; - border: none; - //margin: -10px; - padding: 0; -} - -input[type=radio] { - width: 2em; - margin: 0; - padding: 0; - font-size: 1em; - opacity: 0; -} -input[type=radio] + label{ - display: inline-block; - margin-left: -2em; - line-height: 2em; - font-family: Raleway-SemiBold; - font-size: 14px; -} -input[type=radio] + label > span{ - display: inline-block; - width: 20px; - height: 20px; - margin: 5px; - border-radius: 50%; - background: #6B6A6B; - background-image: linear-gradient(#7D7D7D, #6B6A6B); - vertical-align: bottom; -} -input[type=radio]:checked + label > span{ - background-image: linear-gradient(#7D7D7D, #6B6A6B); -} -input[type=radio]:active + label > span, -input[type=radio]:hover + label > span{ - background-image: linear-gradient(#FFFFFF, #AFAFAF); -} -input[type=radio]:checked + label > span > span, -input[type=radio]:active + label > span > span{ - display: block; - width: 10px; - height: 10px; - margin: 3px; - border: 2px solid #36CDFF; - border-radius: 50%; - background: #00B4EF; -} - -.grayButton { - font-family: Raleway-Bold; - font-size: 13px; - color: black; - padding: 0 10px; - border-radius: 3px; - border-width: 0; - background-image: linear-gradient(#FFFFFF, #AFAFAF); - min-height: 30px; -} -.grayButton:hover { - background-image: linear-gradient(#FFFFFF, #FFFFFF); -} -.grayButton:active { - background-image: linear-gradient(#AFAFAF, #AFAFAF); -} -.grayButton:disabled { - background-image: linear-gradient(#FFFFFF, ##AFAFAF); -} -.blueButton { - font-family: Raleway-Bold; - font-size: 13px; - color: white; - padding: 0 10px; - border-radius: 3px; - border-width: 0; - background-image: linear-gradient(#00B4EF, #1080B8); - min-height: 30px; -} -.blueButton:hover { - background-image: linear-gradient(#00B4EF, #00B4EF); -} -.blueButton:active { - background-image: linear-gradient(#1080B8, #1080B8); -} -.blueButton:disabled { - background-image: linear-gradient(#FFFFFF, #AFAFAF); -} diff --git a/scripts/simplifiedUI/system/html/css/img/jsoneditor-icons.svg b/scripts/simplifiedUI/system/html/css/img/jsoneditor-icons.svg deleted file mode 100644 index 1b40068aad..0000000000 --- a/scripts/simplifiedUI/system/html/css/img/jsoneditor-icons.svg +++ /dev/null @@ -1,893 +0,0 @@ - - - JSON Editor Icons - - - - image/svg+xml - - JSON Editor Icons - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/html/css/img/mt-expand-hover.svg b/scripts/simplifiedUI/system/html/css/img/mt-expand-hover.svg deleted file mode 100644 index a8e84c42ad..0000000000 --- a/scripts/simplifiedUI/system/html/css/img/mt-expand-hover.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/scripts/simplifiedUI/system/html/css/img/mt-expand-normal.svg b/scripts/simplifiedUI/system/html/css/img/mt-expand-normal.svg deleted file mode 100644 index aac349ebda..0000000000 --- a/scripts/simplifiedUI/system/html/css/img/mt-expand-normal.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/scripts/simplifiedUI/system/html/css/img/mt-goto-hover.svg b/scripts/simplifiedUI/system/html/css/img/mt-goto-hover.svg deleted file mode 100644 index 4cad54331a..0000000000 --- a/scripts/simplifiedUI/system/html/css/img/mt-goto-hover.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/scripts/simplifiedUI/system/html/css/img/mt-goto-normal.svg b/scripts/simplifiedUI/system/html/css/img/mt-goto-normal.svg deleted file mode 100644 index ead63329fb..0000000000 --- a/scripts/simplifiedUI/system/html/css/img/mt-goto-normal.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/scripts/simplifiedUI/system/html/css/img/mt-mute-hover.svg b/scripts/simplifiedUI/system/html/css/img/mt-mute-hover.svg deleted file mode 100644 index 9a18ccd933..0000000000 --- a/scripts/simplifiedUI/system/html/css/img/mt-mute-hover.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/scripts/simplifiedUI/system/html/css/img/mt-mute-normal.svg b/scripts/simplifiedUI/system/html/css/img/mt-mute-normal.svg deleted file mode 100644 index 472f03f138..0000000000 --- a/scripts/simplifiedUI/system/html/css/img/mt-mute-normal.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/scripts/simplifiedUI/system/html/css/jsoneditor.css b/scripts/simplifiedUI/system/html/css/jsoneditor.css deleted file mode 100644 index eedef60a7f..0000000000 --- a/scripts/simplifiedUI/system/html/css/jsoneditor.css +++ /dev/null @@ -1,930 +0,0 @@ -/* reset styling (prevent conflicts with bootstrap, materialize.css, etc.) */ - -div.jsoneditor input { - height: auto; - border: inherit; -} - -div.jsoneditor input:focus { - border: none !important; - box-shadow: none !important; -} - -div.jsoneditor table { - border-collapse: collapse; - width: auto; -} - -div.jsoneditor td, -div.jsoneditor th { - padding: 0; - display: table-cell; - text-align: left; - vertical-align: inherit; - border-radius: inherit; -} - - -div.jsoneditor-field, -div.jsoneditor-value, -div.jsoneditor-readonly { - border: 1px solid transparent; - min-height: 16px; - min-width: 32px; - padding: 2px; - margin: 1px; - word-wrap: break-word; - float: left; -} - -/* adjust margin of p elements inside editable divs, needed for Opera, IE */ - -div.jsoneditor-field p, -div.jsoneditor-value p { - margin: 0; -} - -div.jsoneditor-value { - word-break: break-word; -} - -div.jsoneditor-readonly { - min-width: 16px; - color: red; -} - -div.jsoneditor-empty { - border-color: lightgray; - border-style: dashed; - border-radius: 2px; -} - -div.jsoneditor-field.jsoneditor-empty::after, -div.jsoneditor-value.jsoneditor-empty::after { - pointer-events: none; - color: lightgray; - font-size: 8pt; -} - -div.jsoneditor-field.jsoneditor-empty::after { - content: "field"; -} - -div.jsoneditor-value.jsoneditor-empty::after { - content: "value"; -} - -div.jsoneditor-value.jsoneditor-url, -a.jsoneditor-value.jsoneditor-url { - color: green; - text-decoration: underline; -} - -a.jsoneditor-value.jsoneditor-url { - display: inline-block; - padding: 2px; - margin: 2px; -} - -a.jsoneditor-value.jsoneditor-url:hover, -a.jsoneditor-value.jsoneditor-url:focus { - color: #ee422e; -} - -div.jsoneditor td.jsoneditor-separator { - padding: 3px 0; - vertical-align: top; - color: gray; -} - -div.jsoneditor-field[contenteditable=true]:focus, -div.jsoneditor-field[contenteditable=true]:hover, -div.jsoneditor-value[contenteditable=true]:focus, -div.jsoneditor-value[contenteditable=true]:hover, -div.jsoneditor-field.jsoneditor-highlight, -div.jsoneditor-value.jsoneditor-highlight { - background-color: #FFFFAB; - border: 1px solid yellow; - border-radius: 2px; -} - -div.jsoneditor-field.jsoneditor-highlight-active, -div.jsoneditor-field.jsoneditor-highlight-active:focus, -div.jsoneditor-field.jsoneditor-highlight-active:hover, -div.jsoneditor-value.jsoneditor-highlight-active, -div.jsoneditor-value.jsoneditor-highlight-active:focus, -div.jsoneditor-value.jsoneditor-highlight-active:hover { - background-color: #ffee00; - border: 1px solid #ffc700; - border-radius: 2px; -} - -div.jsoneditor-value.jsoneditor-string { - color: #008000; -} - -div.jsoneditor-value.jsoneditor-object, -div.jsoneditor-value.jsoneditor-array { - min-width: 16px; - color: #808080; -} - -div.jsoneditor-value.jsoneditor-number { - color: #ee422e; -} - -div.jsoneditor-value.jsoneditor-boolean { - color: #ff8c00; -} - -div.jsoneditor-value.jsoneditor-null { - color: #004ED0; -} - -div.jsoneditor-value.jsoneditor-invalid { - color: #000000; -} - -div.jsoneditor-tree button { - width: 24px; - height: 24px; - padding: 0; - margin: 0; - border: none; - cursor: pointer; - background: transparent url("img/jsoneditor-icons.svg"); -} - -div.jsoneditor-mode-view tr.jsoneditor-expandable td.jsoneditor-tree, -div.jsoneditor-mode-form tr.jsoneditor-expandable td.jsoneditor-tree { - cursor: pointer; -} - -div.jsoneditor-tree button.jsoneditor-collapsed { - background-position: 0 -48px; -} - -div.jsoneditor-tree button.jsoneditor-expanded { - background-position: 0 -72px; -} - -div.jsoneditor-tree button.jsoneditor-contextmenu { - background-position: -48px -72px; -} - -div.jsoneditor-tree button.jsoneditor-contextmenu:hover, -div.jsoneditor-tree button.jsoneditor-contextmenu:focus, -div.jsoneditor-tree button.jsoneditor-contextmenu.jsoneditor-selected, -tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-contextmenu { - background-position: -48px -48px; -} - -div.jsoneditor-tree *:focus { - outline: none; -} - -div.jsoneditor-tree button:focus { - /* TODO: nice outline for buttons with focus - outline: #97B0F8 solid 2px; - box-shadow: 0 0 8px #97B0F8; - */ - background-color: #f5f5f5; - outline: #e5e5e5 solid 1px; -} - -div.jsoneditor-tree button.jsoneditor-invisible { - visibility: hidden; - background: none; -} - -#userdata-editor{ - height:100%; -} - -div.jsoneditor { - color: #1A1A1A; - border: 1px solid #2e2e2e; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; - width: 100%; - overflow: hidden; - position: relative; - padding: 0; - line-height: 100%; -} - -div.jsoneditor-tree table.jsoneditor-tree { - border-collapse: collapse; - border-spacing: 0; - width: 100%; - margin: 0; -} - -div.jsoneditor-outer { - width: 100%; - margin: -35px 0 0 0; - padding: 0 0 0 0; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; - overflow-y: auto; -} - -.ace-jsoneditor { - min-height: 150px; - height: auto !important; -} - -div.jsoneditor-tree { - width: 100%; - position: relative; -} - -textarea.jsoneditor-text { - width: 100%; - margin: 0; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; - outline-width: 0; - border: none; - background-color: white; - resize: none; -} - -tr.jsoneditor-highlight, -tr.jsoneditor-selected { - background-color: #e6e6e6; -} - -tr.jsoneditor-selected button.jsoneditor-dragarea, -tr.jsoneditor-selected button.jsoneditor-contextmenu { - visibility: hidden; -} - -tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-dragarea, -tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-contextmenu { - visibility: visible; -} - -div.jsoneditor-tree button.jsoneditor-dragarea { - background: url("img/jsoneditor-icons.svg") -72px -72px; - cursor: move; -} - -div.jsoneditor-tree button.jsoneditor-dragarea:hover, -div.jsoneditor-tree button.jsoneditor-dragarea:focus, -tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-dragarea { - background-position: -72px -48px; -} - -div.jsoneditor tr, -div.jsoneditor th, -div.jsoneditor td { - padding: 0; - margin: 0; - overflow: visible; -} - -div.jsoneditor td { - vertical-align: top; -} - -div.jsoneditor td.jsoneditor-tree { - vertical-align: top; -} - -div.jsoneditor-field, -div.jsoneditor-value, -div.jsoneditor td, -div.jsoneditor th, -div.jsoneditor textarea, -.jsoneditor-schema-error { - font-family: droid sans mono, consolas, monospace, courier new, courier, sans-serif; - font-size: 10pt; - color: grey; -} - -/* popover */ - -.jsoneditor-schema-error { - cursor: default; - display: inline-block; - /*font-family: arial, sans-serif;*/ - height: 24px; - line-height: 24px; - position: relative; - text-align: center; - width: 24px; -} - -div.jsoneditor-tree .jsoneditor-schema-error { - width: 24px; - height: 24px; - padding: 0; - margin: 0 4px 0 0; - background: url("img/jsoneditor-icons.svg") -168px -48px; -} - -.jsoneditor-schema-error .jsoneditor-popover { - background-color: #4c4c4c; - border-radius: 3px; - box-shadow: 0 0 5px rgba(0,0,0,0.4); - color: #fff; - display: none; - padding: 7px 10px; - position: absolute; - width: 200px; - z-index: 4; -} - -.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-above { - bottom: 32px; - left: -98px; -} - -.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-below { - top: 32px; - left: -98px; -} - -.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-left { - top: -7px; - right: 32px; -} - -.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-right { - top: -7px; - left: 32px; -} - -.jsoneditor-schema-error .jsoneditor-popover:before { - border-right: 7px solid transparent; - border-left: 7px solid transparent; - content: ''; - display: block; - left: 50%; - margin-left: -7px; - position: absolute; -} - -.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-above:before { - border-top: 7px solid #4c4c4c; - bottom: -7px; -} - -.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-below:before { - border-bottom: 7px solid #4c4c4c; - top: -7px; -} - -.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-left:before { - border-left: 7px solid #4c4c4c; - border-top: 7px solid transparent; - border-bottom: 7px solid transparent; - content: ''; - top: 19px; - right: -14px; - left: inherit; - margin-left: inherit; - margin-top: -7px; - position: absolute; -} - -.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-right:before { - border-right: 7px solid #4c4c4c; - border-top: 7px solid transparent; - border-bottom: 7px solid transparent; - content: ''; - top: 19px; - left: -14px; - margin-left: inherit; - margin-top: -7px; - position: absolute; -} - -.jsoneditor-schema-error:hover .jsoneditor-popover, -.jsoneditor-schema-error:focus .jsoneditor-popover { - display: block; - -webkit-animation: fade-in .3s linear 1, move-up .3s linear 1; - -moz-animation: fade-in .3s linear 1, move-up .3s linear 1; - -ms-animation: fade-in .3s linear 1, move-up .3s linear 1; -} - -@-webkit-keyframes fade-in { - from { - opacity: 0; - } - - to { - opacity: 1; - } -} - -@-moz-keyframes fade-in { - from { - opacity: 0; - } - - to { - opacity: 1; - } -} - -@-ms-keyframes fade-in { - from { - opacity: 0; - } - - to { - opacity: 1; - } -} - -/*@-webkit-keyframes move-up {*/ - -/*from { bottom: 24px; }*/ - -/*to { bottom: 32px; }*/ - -/*}*/ - -/*@-moz-keyframes move-up {*/ - -/*from { bottom: 24px; }*/ - -/*to { bottom: 32px; }*/ - -/*}*/ - -/*@-ms-keyframes move-up {*/ - -/*from { bottom: 24px; }*/ - -/*to { bottom: 32px; }*/ - -/*}*/ - -/* JSON schema errors displayed at the bottom of the editor in mode text and code */ - -.jsoneditor .jsoneditor-text-errors { - width: 100%; - border-collapse: collapse; - background-color: #ffef8b; - border-top: 1px solid #ffd700; -} - -.jsoneditor .jsoneditor-text-errors td { - padding: 3px 6px; - vertical-align: middle; -} - -.jsoneditor-text-errors .jsoneditor-schema-error { - border: none; - width: 24px; - height: 24px; - padding: 0; - margin: 0 4px 0 0; - background: url("img/jsoneditor-icons.svg") -168px -48px; -} -/* ContextMenu - main menu */ - -div.jsoneditor-contextmenu-root { - position: relative; - width: 0; - height: 0; -} - -div.jsoneditor-contextmenu { - position: absolute; - box-sizing: content-box; - z-index: 998; -} - -div.jsoneditor-contextmenu ul, -div.jsoneditor-contextmenu li { - box-sizing: content-box; -} - -div.jsoneditor-contextmenu ul { - position: relative; - left: 0; - top: 0; - width: 124px; - background: white; - border: 1px solid #d3d3d3; - box-shadow: 2px 2px 12px rgba(128, 128, 128, 0.3); - list-style: none; - margin: 0; - padding: 0; -} - -div.jsoneditor-contextmenu ul li button { - padding: 0; - margin: 0; - width: 124px; - height: 24px; - border: none; - cursor: pointer; - color: #4d4d4d; - background: transparent; - font-size: 10pt; - font-family: arial, sans-serif; - box-sizing: border-box; - line-height: 26px; - text-align: left; -} - -/* Fix button padding in firefox */ - -div.jsoneditor-contextmenu ul li button::-moz-focus-inner { - padding: 0; - border: 0; -} - -div.jsoneditor-contextmenu ul li button:hover, -div.jsoneditor-contextmenu ul li button:focus { - color: #1a1a1a; - background-color: #f5f5f5; - outline: none; -} - -div.jsoneditor-contextmenu ul li button.jsoneditor-default { - width: 92px; -} - -div.jsoneditor-contextmenu ul li button.jsoneditor-expand { - float: right; - width: 32px; - height: 24px; - border-left: 1px solid #e5e5e5; -} - -div.jsoneditor-contextmenu div.jsoneditor-icon { - float: left; - width: 24px; - height: 24px; - border: none; - padding: 0; - margin: 0; - background-image: url("img/jsoneditor-icons.svg"); -} - -div.jsoneditor-contextmenu ul li button div.jsoneditor-expand { - float: right; - width: 24px; - height: 24px; - padding: 0; - margin: 0 4px 0 0; - background: url("img/jsoneditor-icons.svg") 0 -72px; - opacity: 0.4; -} - -div.jsoneditor-contextmenu ul li button:hover div.jsoneditor-expand, -div.jsoneditor-contextmenu ul li button:focus div.jsoneditor-expand, -div.jsoneditor-contextmenu ul li.jsoneditor-selected div.jsoneditor-expand, -div.jsoneditor-contextmenu ul li button.jsoneditor-expand:hover div.jsoneditor-expand, -div.jsoneditor-contextmenu ul li button.jsoneditor-expand:focus div.jsoneditor-expand { - opacity: 1; -} - -div.jsoneditor-contextmenu div.jsoneditor-separator { - height: 0; - border-top: 1px solid #e5e5e5; - padding-top: 5px; - margin-top: 5px; -} - -div.jsoneditor-contextmenu button.jsoneditor-remove > div.jsoneditor-icon { - background-position: -24px -24px; -} - -div.jsoneditor-contextmenu button.jsoneditor-remove:hover > div.jsoneditor-icon, -div.jsoneditor-contextmenu button.jsoneditor-remove:focus > div.jsoneditor-icon { - background-position: -24px 0; -} - -div.jsoneditor-contextmenu button.jsoneditor-append > div.jsoneditor-icon { - background-position: 0 -24px; -} - -div.jsoneditor-contextmenu button.jsoneditor-append:hover > div.jsoneditor-icon, -div.jsoneditor-contextmenu button.jsoneditor-append:focus > div.jsoneditor-icon { - background-position: 0 0; -} - -div.jsoneditor-contextmenu button.jsoneditor-insert > div.jsoneditor-icon { - background-position: 0 -24px; -} - -div.jsoneditor-contextmenu button.jsoneditor-insert:hover > div.jsoneditor-icon, -div.jsoneditor-contextmenu button.jsoneditor-insert:focus > div.jsoneditor-icon { - background-position: 0 0; -} - -div.jsoneditor-contextmenu button.jsoneditor-duplicate > div.jsoneditor-icon { - background-position: -48px -24px; -} - -div.jsoneditor-contextmenu button.jsoneditor-duplicate:hover > div.jsoneditor-icon, -div.jsoneditor-contextmenu button.jsoneditor-duplicate:focus > div.jsoneditor-icon { - background-position: -48px 0; -} - -div.jsoneditor-contextmenu button.jsoneditor-sort-asc > div.jsoneditor-icon { - background-position: -168px -24px; -} - -div.jsoneditor-contextmenu button.jsoneditor-sort-asc:hover > div.jsoneditor-icon, -div.jsoneditor-contextmenu button.jsoneditor-sort-asc:focus > div.jsoneditor-icon { - background-position: -168px 0; -} - -div.jsoneditor-contextmenu button.jsoneditor-sort-desc > div.jsoneditor-icon { - background-position: -192px -24px; -} - -div.jsoneditor-contextmenu button.jsoneditor-sort-desc:hover > div.jsoneditor-icon, -div.jsoneditor-contextmenu button.jsoneditor-sort-desc:focus > div.jsoneditor-icon { - background-position: -192px 0; -} - -/* ContextMenu - sub menu */ - -div.jsoneditor-contextmenu ul li button.jsoneditor-selected, -div.jsoneditor-contextmenu ul li button.jsoneditor-selected:hover, -div.jsoneditor-contextmenu ul li button.jsoneditor-selected:focus { - color: white; - background-color: #ee422e; -} - -div.jsoneditor-contextmenu ul li { - overflow: hidden; -} - -div.jsoneditor-contextmenu ul li ul { - display: none; - position: relative; - left: -10px; - top: 0; - border: none; - box-shadow: inset 0 0 10px rgba(128, 128, 128, 0.5); - padding: 0 10px; - /* TODO: transition is not supported on IE8-9 */ - -webkit-transition: all 0.3s ease-out; - -moz-transition: all 0.3s ease-out; - -o-transition: all 0.3s ease-out; - transition: all 0.3s ease-out; -} - - - -div.jsoneditor-contextmenu ul li ul li button { - padding-left: 24px; - animation: all ease-in-out 1s; -} - -div.jsoneditor-contextmenu ul li ul li button:hover, -div.jsoneditor-contextmenu ul li ul li button:focus { - background-color: #f5f5f5; -} - -div.jsoneditor-contextmenu button.jsoneditor-type-string > div.jsoneditor-icon { - background-position: -144px -24px; -} - -div.jsoneditor-contextmenu button.jsoneditor-type-string:hover > div.jsoneditor-icon, -div.jsoneditor-contextmenu button.jsoneditor-type-string:focus > div.jsoneditor-icon, -div.jsoneditor-contextmenu button.jsoneditor-type-string.jsoneditor-selected > div.jsoneditor-icon { - background-position: -144px 0; -} - -div.jsoneditor-contextmenu button.jsoneditor-type-auto > div.jsoneditor-icon { - background-position: -120px -24px; -} - -div.jsoneditor-contextmenu button.jsoneditor-type-auto:hover > div.jsoneditor-icon, -div.jsoneditor-contextmenu button.jsoneditor-type-auto:focus > div.jsoneditor-icon, -div.jsoneditor-contextmenu button.jsoneditor-type-auto.jsoneditor-selected > div.jsoneditor-icon { - background-position: -120px 0; -} - -div.jsoneditor-contextmenu button.jsoneditor-type-object > div.jsoneditor-icon { - background-position: -72px -24px; -} - -div.jsoneditor-contextmenu button.jsoneditor-type-object:hover > div.jsoneditor-icon, -div.jsoneditor-contextmenu button.jsoneditor-type-object:focus > div.jsoneditor-icon, -div.jsoneditor-contextmenu button.jsoneditor-type-object.jsoneditor-selected > div.jsoneditor-icon { - background-position: -72px 0; -} - -div.jsoneditor-contextmenu button.jsoneditor-type-array > div.jsoneditor-icon { - background-position: -96px -24px; -} - -div.jsoneditor-contextmenu button.jsoneditor-type-array:hover > div.jsoneditor-icon, -div.jsoneditor-contextmenu button.jsoneditor-type-array:focus > div.jsoneditor-icon, -div.jsoneditor-contextmenu button.jsoneditor-type-array.jsoneditor-selected > div.jsoneditor-icon { - background-position: -96px 0; -} - -div.jsoneditor-contextmenu button.jsoneditor-type-modes > div.jsoneditor-icon { - background-image: none; - width: 6px; -} -div.jsoneditor-menu { - width: 100%; - height: 35px; - padding: 2px; - margin: 0; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; - color: white; - background-color: #2e2e2e; - border-bottom: 1px solid #2e2e2e; -} - -div.jsoneditor-menu > button, -div.jsoneditor-menu > div.jsoneditor-modes > button { - width: 26px; - height: 26px; - margin: 2px; - padding: 0; - border-radius: 2px; - border: 1px solid transparent; - background: transparent url("img/jsoneditor-icons.svg"); - color: white; - opacity: 0.8; - font-family: arial, sans-serif; - font-size: 10pt; - float: left; -} - -div.jsoneditor-menu > button:hover, -div.jsoneditor-menu > div.jsoneditor-modes > button:hover { - background-color: rgba(255,255,255,0.2); - border: 1px solid rgba(255,255,255,0.4); -} - -div.jsoneditor-menu > button:focus, -div.jsoneditor-menu > button:active, -div.jsoneditor-menu > div.jsoneditor-modes > button:focus, -div.jsoneditor-menu > div.jsoneditor-modes > button:active { - background-color: rgba(255,255,255,0.3); -} - -div.jsoneditor-menu > button:disabled, -div.jsoneditor-menu > div.jsoneditor-modes > button:disabled { - opacity: 0.5; -} - -div.jsoneditor-menu > button.jsoneditor-collapse-all { - background-position: 0 -96px; -} - -div.jsoneditor-menu > button.jsoneditor-expand-all { - background-position: 0 -120px; -} - -div.jsoneditor-menu > button.jsoneditor-undo { - background-position: -24px -96px; -} - -div.jsoneditor-menu > button.jsoneditor-undo:disabled { - background-position: -24px -120px; -} - -div.jsoneditor-menu > button.jsoneditor-redo { - background-position: -48px -96px; -} - -div.jsoneditor-menu > button.jsoneditor-redo:disabled { - background-position: -48px -120px; -} - -div.jsoneditor-menu > button.jsoneditor-compact { - background-position: -72px -96px; -} - -div.jsoneditor-menu > button.jsoneditor-format { - background-position: -72px -120px; -} - -div.jsoneditor-menu > div.jsoneditor-modes { - display: inline-block; - float: left; -} - -div.jsoneditor-menu > div.jsoneditor-modes > button { - background-image: none; - width: auto; - padding-left: 6px; - padding-right: 6px; -} - -div.jsoneditor-menu > button.jsoneditor-separator, -div.jsoneditor-menu > div.jsoneditor-modes > button.jsoneditor-separator { - margin-left: 10px; -} - -div.jsoneditor-menu a { - font-family: arial, sans-serif; - font-size: 10pt; - color: white; - opacity: 0.8; - vertical-align: middle; -} - -div.jsoneditor-menu a:hover { - opacity: 1; -} - -div.jsoneditor-menu a.jsoneditor-poweredBy { - font-size: 8pt; - position: absolute; - right: 0; - top: 0; - padding: 10px; -} -table.jsoneditor-search input, -table.jsoneditor-search div.jsoneditor-results { - font-family: arial, sans-serif; - font-size: 10pt; - color: #1A1A1A; - background: transparent; - /* For Firefox */ -} - -table.jsoneditor-search div.jsoneditor-results { - color: white; - padding-right: 5px; - line-height: 24px; -} - -table.jsoneditor-search { - position: absolute; - right: 4px; - top: 4px; - border-collapse: collapse; - border-spacing: 0; -} - -table.jsoneditor-search div.jsoneditor-frame { - border: 1px solid transparent; - background-color: white; - padding: 0 2px; - margin: 0; -} - -table.jsoneditor-search div.jsoneditor-frame table { - border-collapse: collapse; -} - -table.jsoneditor-search input { - width: 120px; - border: none; - outline: none; - margin: 1px; - line-height: 20px; -} - -table.jsoneditor-search button { - width: 16px; - height: 24px; - padding: 0; - margin: 0; - border: none; - background: url("img/jsoneditor-icons.svg"); - vertical-align: top; -} - -table.jsoneditor-search button:hover { - background-color: transparent; -} - -table.jsoneditor-search button.jsoneditor-refresh { - width: 18px; - background-position: -99px -73px; -} - -table.jsoneditor-search button.jsoneditor-next { - cursor: pointer; - background-position: -124px -73px; -} - -table.jsoneditor-search button.jsoneditor-next:hover { - background-position: -124px -49px; -} - -table.jsoneditor-search button.jsoneditor-previous { - cursor: pointer; - background-position: -148px -73px; - margin-right: 2px; -} - -table.jsoneditor-search button.jsoneditor-previous:hover { - background-position: -148px -49px; -} diff --git a/scripts/simplifiedUI/system/html/css/marketplaces.css b/scripts/simplifiedUI/system/html/css/marketplaces.css deleted file mode 100644 index 04c132eab1..0000000000 --- a/scripts/simplifiedUI/system/html/css/marketplaces.css +++ /dev/null @@ -1,224 +0,0 @@ -/* -// -// Copyright 2016 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 -*/ - -/* - CSS rules copied from edit-style.css. - Edit-style.css is not used in its entirety because don't want custom scrollbars; default scrollbar styling is used in order - to match other marketplace pages. -*/ - -@font-face { - font-family: Raleway-Regular; - src: url(../../../../resources/fonts/Raleway-Regular.ttf), /* Windows production */ - url(../../../../fonts/Raleway-Regular.ttf), /* OSX production */ - url(../../../../interface/resources/fonts/Raleway-Regular.ttf); /* Development, running script in /HiFi/examples */ -} - -@font-face { - font-family: Raleway-Bold; - src: url(../../../../resources/fonts/Raleway-Bold.ttf), - url(../../../../fonts/Raleway-Bold.ttf), - url(../../../../interface/resources/fonts/Raleway-Bold.ttf); -} - -@font-face { - font-family: Raleway-SemiBold; - src: url(../../../../resources/fonts/Raleway-SemiBold.ttf), - url(../../../../fonts/Raleway-SemiBold.ttf), - url(../../../../interface/resources/fonts/Raleway-SemiBold.ttf); -} - -@font-face { - font-family: FiraSans-SemiBold; - src: url(../../../../resources/fonts/FiraSans-SemiBold.ttf), - url(../../../../fonts/FiraSans-SemiBold.ttf), - url(../../../../interface/resources/fonts/FiraSans-SemiBold.ttf); -} - -* { - margin: 0; - padding: 0; -} - -body { - padding: 21px 21px 21px 21px; - - color: #afafaf; - background-color: #404040; - font-family: Raleway-Regular; - font-size: 15px; - - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - - overflow-x: hidden; - overflow-y: auto; -} - -input[type=button] { - font-family: Raleway-Bold; - font-size: 13px; - text-transform: uppercase; - vertical-align: top; - height: 28px; - min-width: 120px; - padding: 0px 18px; - margin-right: 6px; - border-radius: 5px; - border: none; - color: #fff; - background-color: #000; - background: linear-gradient(#343434 20%, #000 100%); - cursor: pointer; -} - -input[type=button].blue { - color: #fff; - background-color: #1080b8; - background: linear-gradient(#00b4ef 20%, #1080b8 100%); -} - - -/* - Marketplaces-specific CSS. -*/ - -body { - background: white; - padding: 0 0 0 0; - font-family:Raleway-SemiBold; -} -.marketplaces-container { - display: inline-block; - color: black; - width: 94%; - margin-left: 3%; - height: 100%; -} -.marketplaces-title { - margin-top: 45px; - margin-bottom: 20px; -} -.marketplaces-intro-text { - margin-bottom: 30px; -} -.marketplace-tile { - float:left; - width: 100%; - margin-bottom: 25px; -} -.marketplace-tile-first-column { - text-align: center; - float: left; - width: 33%; -} -.marketplace-tile-second-column { - float: left; - margin-left:4%; - width: 62%; -} -.exploreButton { - font-size: 16px !important; - width: 200px !important; - height: 45px !important; - margin-top: 20px; - margin-bottom: 30px; -} -.tile-divider { - width: 100%; - margin-left: 0%; - display: block; - height: 1px; - border: 0; - border-top: 1px solid lightgrey; - margin: 1em 0; - padding: 0; - margin-bottom: 30px; -} -.marketplace-tile-description { - margin-top: 15px; - margin-bottom: 30px; -} -.marketplace-tile-image { - margin-top:15px; - max-width: 256px; - height: 128px; - margin-bottom:60px; - -webkit-box-shadow: -1px 4px 16px 0px rgba(0, 0, 0, 0.48); - -moz-box-shadow: -1px 4px 16px 0px rgba(0, 0, 0, 0.48); - box-shadow: -1px 4px 16px 0px rgba(0, 0, 0, 0.48); -} -.marketplace-clara-steps { - padding-left: 15px; -} -.marketplace-clara-steps > li { - margin-top: 5px; -} - -#marketplace-navigation { - width: 100%; - height: 50px; - background: #00b4ef; - position: fixed; - bottom: 0; -} -#marketplace-navigation .glyph { - /* - // Target look but can't use font in injected script. - font-family: HiFi-Glyphs; - font-size: 40px; - margin-left: 20px; - */ - font-family: sans-serif; - font-size: 24px; - margin-left: 20px; - margin-right: 3px; - color: #fff; - line-height: 50px; -} -#marketplace-navigation .text { - color: #fff; - font-size: 18px; - line-height: 50px; - vertical-align: top; - position: relative; - top: 1px; -} -#marketplace-navigation input { - position: absolute; - right: 20px; - margin-top: 12px; - padding-left: 15px; - padding-right: 15px; -} - -@media (max-width:768px) { - .marketplace-tile-first-column { - float: left; - width: 100%; - } - .marketplace-tile-second-column { - float: left; - width: 100%; - } - .exploreButton-holder { - width:100%; - text-align:center; - } - .tile-divider { - width: 100%; - margin-left: 0; - } - .marketplace-tile-image { - margin-bottom: 15px; - } -} diff --git a/scripts/simplifiedUI/system/html/css/miniTablet.css b/scripts/simplifiedUI/system/html/css/miniTablet.css deleted file mode 100644 index 7598332d28..0000000000 --- a/scripts/simplifiedUI/system/html/css/miniTablet.css +++ /dev/null @@ -1,92 +0,0 @@ -/* -miniTablet.css - -Created by David Rowe on 20 Aug 2018. -Copyright 2018 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 -*/ - -* { - box-sizing: border-box; - padding: 0; - margin: 0; - user-select: none; -} - -html { - background-color: #404040; -} - -body { - height: 100%; -} - -section { - background-color: #404040; - position: relative; - padding: 16px 16px; -} - -.button { - width: 116px; - height: 84px; - margin-top: 16px; - text-align: center; -} - - .button:first-child { - margin-top: 0; - } - -img { - width: 40px; -} - -#mute { - padding-top: 19px; - background-size: 100% 100%; - background-image: url("./img/mt-mute-normal.svg"); -} - - #mute:hover { - background-image: url("./img/mt-mute-hover.svg"); - } - -#goto { - padding-top: 19px; - background-size: 100% 100%; - background-image: url("./img/mt-goto-normal.svg"); -} - - #goto:hover { - background-image: url("./img/mt-goto-hover.svg"); - } - - #goto:hover.unhover { - background-image: url("./img/mt-goto-normal.svg"); - } - -#expand { - position: absolute; - right: 1px; - bottom: -1px; - width: 50px; - height: 50px; - background-size: 100% 100%; - background-image: url("./img/mt-expand-normal.svg"); -} - - #expand:hover { - background-image: url("./img/mt-expand-hover.svg"); - } - - #expand:hover.unhover { - background-image: url("./img/mt-expand-normal.svg"); - } - - #expand img { - width:34px; - margin-top: 7px; - } diff --git a/scripts/simplifiedUI/system/html/entityList.html b/scripts/simplifiedUI/system/html/entityList.html deleted file mode 100644 index 986e5c09b0..0000000000 --- a/scripts/simplifiedUI/system/html/entityList.html +++ /dev/null @@ -1,93 +0,0 @@ - - - - Entity List - - - - - - - - - - - - - -
- -
- - -
- - - -
-
-
-
-
- -
-
-
- -
- - -
-
-
-
- Y -
- -
- - -
-
-
- - - - -
-
-
- -
-
-
- -
-
-
- There are no entities to display. Please check your filters or create an entity to begin. -
-
-
- - - diff --git a/scripts/simplifiedUI/system/html/gridControls.html b/scripts/simplifiedUI/system/html/gridControls.html deleted file mode 100644 index 8d6ee34bc0..0000000000 --- a/scripts/simplifiedUI/system/html/gridControls.html +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - - - -
-
- -
- - -
-
-
- -
- - -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
- -
-
-
-
-
- -
- - -
-
-
- - diff --git a/scripts/simplifiedUI/system/html/img/blast_icon.svg b/scripts/simplifiedUI/system/html/img/blast_icon.svg deleted file mode 100644 index 31df8e7f53..0000000000 --- a/scripts/simplifiedUI/system/html/img/blast_icon.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - diff --git a/scripts/simplifiedUI/system/html/img/blocks-tile.png b/scripts/simplifiedUI/system/html/img/blocks-tile.png deleted file mode 100644 index 49de535c1c..0000000000 Binary files a/scripts/simplifiedUI/system/html/img/blocks-tile.png and /dev/null differ diff --git a/scripts/simplifiedUI/system/html/img/button-snap-print.svg b/scripts/simplifiedUI/system/html/img/button-snap-print.svg deleted file mode 100644 index d1570711d7..0000000000 --- a/scripts/simplifiedUI/system/html/img/button-snap-print.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/html/img/clara-tile.png b/scripts/simplifiedUI/system/html/img/clara-tile.png deleted file mode 100644 index ae431dd510..0000000000 Binary files a/scripts/simplifiedUI/system/html/img/clara-tile.png and /dev/null differ diff --git a/scripts/simplifiedUI/system/html/img/expand.svg b/scripts/simplifiedUI/system/html/img/expand.svg deleted file mode 100644 index f57e624374..0000000000 --- a/scripts/simplifiedUI/system/html/img/expand.svg +++ /dev/null @@ -1,85 +0,0 @@ - - - -image/svg+xml - - - - - - - - - \ No newline at end of file diff --git a/scripts/simplifiedUI/system/html/img/fb_icon.svg b/scripts/simplifiedUI/system/html/img/fb_icon.svg deleted file mode 100644 index 6d67d17bb2..0000000000 --- a/scripts/simplifiedUI/system/html/img/fb_icon.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - diff --git a/scripts/simplifiedUI/system/html/img/hifi-marketplace-tile.png b/scripts/simplifiedUI/system/html/img/hifi-marketplace-tile.png deleted file mode 100644 index 9a95c081a0..0000000000 Binary files a/scripts/simplifiedUI/system/html/img/hifi-marketplace-tile.png and /dev/null differ diff --git a/scripts/simplifiedUI/system/html/img/hifi_icon.svg b/scripts/simplifiedUI/system/html/img/hifi_icon.svg deleted file mode 100644 index acbb98a3b3..0000000000 --- a/scripts/simplifiedUI/system/html/img/hifi_icon.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - diff --git a/scripts/simplifiedUI/system/html/img/loader.gif b/scripts/simplifiedUI/system/html/img/loader.gif deleted file mode 100644 index c464703c84..0000000000 Binary files a/scripts/simplifiedUI/system/html/img/loader.gif and /dev/null differ diff --git a/scripts/simplifiedUI/system/html/img/snapshotIcon.png b/scripts/simplifiedUI/system/html/img/snapshotIcon.png deleted file mode 100644 index 5cb2742a32..0000000000 Binary files a/scripts/simplifiedUI/system/html/img/snapshotIcon.png and /dev/null differ diff --git a/scripts/simplifiedUI/system/html/img/twitter_icon.svg b/scripts/simplifiedUI/system/html/img/twitter_icon.svg deleted file mode 100644 index 0393d963f2..0000000000 --- a/scripts/simplifiedUI/system/html/img/twitter_icon.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - diff --git a/scripts/simplifiedUI/system/html/js/SnapshotReview.js b/scripts/simplifiedUI/system/html/js/SnapshotReview.js deleted file mode 100644 index 1e8be9d644..0000000000 --- a/scripts/simplifiedUI/system/html/js/SnapshotReview.js +++ /dev/null @@ -1,814 +0,0 @@ -/*jslint browser:true */ -/*jslint maxlen: 180*/ -"use strict"; -// -// SnapshotReview.js -// scripts/system/html/js/ -// -// Created by Howard Stearns 8/22/2016 -// Copyright 2016 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 -// - -var paths = []; -var idCounter = 0; -var imageCount = 0; -var blastShareText = "Blast to my Connections", - blastAlreadySharedText = "Already Blasted to Connections", - hifiShareText = "Share to Snaps Feed", - hifiAlreadySharedText = "Already Shared to Snaps Feed", - facebookShareText = "Share to Facebook", - twitterShareText = "Share to Twitter", - shareButtonLabelTextActive = "SHARE:", - shareButtonLabelTextInactive = "SHARE"; - -function fileExtensionMatches(filePath, extension) { - return filePath.split('.').pop().toLowerCase() === extension; -} - -function showSetupInstructions() { - var snapshotImagesDiv = document.getElementById("snapshot-images"); - snapshotImagesDiv.className = "snapshotInstructions"; - snapshotImagesDiv.innerHTML = 'Snapshot Instructions' + - '
' + - '

Take and share snaps and GIFs with people in High Fidelity, Facebook, and Twitter.

' + - "

Setup Instructions

" + - "

Before you can begin taking snaps, please choose where you'd like to save snaps on your computer:

" + - '
' + - '
' + - '' + - '
'; - document.getElementById("snap-button").disabled = true; -} -function showSetupComplete() { - var snapshotImagesDiv = document.getElementById("snapshot-images"); - snapshotImagesDiv.className = "snapshotInstructions"; - snapshotImagesDiv.innerHTML = 'Snapshot Instructions' + - '
' + - '
' + - '

Snapshot location set.

' + - '

Press the big red button to take a snap!

' + - '
'; - document.getElementById("snap-button").disabled = false; -} -function showSnapshotInstructions() { - var snapshotImagesDiv = document.getElementById("snapshot-images"); - snapshotImagesDiv.className = "snapshotInstructions"; - snapshotImagesDiv.innerHTML = 'Snapshot Instructions' + - '
' + - '

Take and share snaps and GIFs with people in High Fidelity, Facebook, and Twitter.

' + - '
' + - '
' + - '

Press the big red button to take a snap!

' + - '
'; -} -function chooseSnapshotLocation() { - EventBridge.emitWebEvent(JSON.stringify({ - type: "snapshot", - action: "chooseSnapshotLocation" - })); -} -function login() { - EventBridge.emitWebEvent(JSON.stringify({ - type: "snapshot", - action: "login" - })); -} -function clearImages() { - var snapshotImagesDiv = document.getElementById("snapshot-images"); - snapshotImagesDiv.classList.remove("snapshotInstructions"); - while (snapshotImagesDiv.hasChildNodes()) { - snapshotImagesDiv.removeChild(snapshotImagesDiv.lastChild); - } - paths = []; - imageCount = 0; - idCounter = 0; -} - -function selectImageWithHelpText(selectedID, isSelected) { - if (selectedID.id) { - selectedID = selectedID.id; // sometimes (?), `selectedID` is passed as an HTML object to these functions; we just want the ID - } - var imageContainer = document.getElementById(selectedID), - image = document.getElementById(selectedID + 'img'), - shareBar = document.getElementById(selectedID + "shareBar"), - helpTextDiv = document.getElementById(selectedID + "helpTextDiv"), - showShareButtonsButtonDiv = document.getElementById(selectedID + "showShareButtonsButtonDiv"), - itr, - containers = document.getElementsByClassName("shareControls"); - - if (isSelected) { - showShareButtonsButtonDiv.onclick = function () { selectImageWithHelpText(selectedID, false); }; - showShareButtonsButtonDiv.classList.remove("inactive"); - showShareButtonsButtonDiv.classList.add("active"); - - image.onclick = function () { selectImageWithHelpText(selectedID, false); }; - imageContainer.style.outline = "4px solid #00b4ef"; - imageContainer.style.outlineOffset = "-4px"; - - shareBar.style.backgroundColor = "rgba(0, 0, 0, 0.45)"; - shareBar.style.pointerEvents = "initial"; - - helpTextDiv.style.visibility = "visible"; - - for (itr = 0; itr < containers.length; itr += 1) { - var parentID = containers[itr].id.slice(0, 2); - if (parentID !== selectedID) { - selectImageWithHelpText(parentID, false); - } - } - } else { - showShareButtonsButtonDiv.onclick = function () { selectImageWithHelpText(selectedID, true); }; - showShareButtonsButtonDiv.classList.remove("active"); - showShareButtonsButtonDiv.classList.add("inactive"); - - image.onclick = function () { selectImageWithHelpText(selectedID, true); }; - imageContainer.style.outline = "none"; - - shareBar.style.backgroundColor = "rgba(0, 0, 0, 0.0)"; - shareBar.style.pointerEvents = "none"; - - helpTextDiv.style.visibility = "hidden"; - } -} -function selectImageToShare(selectedID, isSelected) { - if (selectedID.id) { - selectedID = selectedID.id; // sometimes (?), `selectedID` is passed as an HTML object to these functions; we just want the ID - } - var imageContainer = document.getElementById(selectedID), - image = document.getElementById(selectedID + 'img'), - shareBar = document.getElementById(selectedID + "shareBar"), - showShareButtonsDots = document.getElementById(selectedID + "showShareButtonsDots"), - showShareButtonsLabel = document.getElementById(selectedID + "showShareButtonsLabel"), - shareButtonsDiv = document.getElementById(selectedID + "shareButtonsDiv"), - shareBarHelp = document.getElementById(selectedID + "shareBarHelp"), - showShareButtonsButtonDiv = document.getElementById(selectedID + "showShareButtonsButtonDiv"), - itr, - containers = document.getElementsByClassName("shareControls"); - - if (isSelected) { - showShareButtonsButtonDiv.onclick = function () { selectImageToShare(selectedID, false); }; - showShareButtonsButtonDiv.classList.remove("inactive"); - showShareButtonsButtonDiv.classList.add("active"); - - image.onclick = function () { selectImageToShare(selectedID, false); }; - imageContainer.style.outline = "4px solid #00b4ef"; - imageContainer.style.outlineOffset = "-4px"; - - shareBar.style.backgroundColor = "rgba(0, 0, 0, 0.45)"; - shareBar.style.pointerEvents = "initial"; - - showShareButtonsDots.style.visibility = "hidden"; - showShareButtonsLabel.innerHTML = shareButtonLabelTextActive; - - shareButtonsDiv.style.visibility = "visible"; - shareBarHelp.style.visibility = "visible"; - - for (itr = 0; itr < containers.length; itr += 1) { - var parentID = containers[itr].id.slice(0, 2); - if (parentID !== selectedID) { - selectImageToShare(parentID, false); - } - } - } else { - showShareButtonsButtonDiv.onclick = function () { selectImageToShare(selectedID, true); }; - showShareButtonsButtonDiv.classList.remove("active"); - showShareButtonsButtonDiv.classList.add("inactive"); - - image.onclick = function () { selectImageToShare(selectedID, true); }; - imageContainer.style.outline = "none"; - - shareBar.style.backgroundColor = "rgba(0, 0, 0, 0.0)"; - shareBar.style.pointerEvents = "none"; - - showShareButtonsDots.style.visibility = "visible"; - showShareButtonsLabel.innerHTML = shareButtonLabelTextInactive; - - shareButtonsDiv.style.visibility = "hidden"; - shareBarHelp.style.visibility = "hidden"; - } -} -function createShareBar(parentID, isLoggedIn, canShare, isGif, blastButtonDisabled, hifiButtonDisabled, canBlast) { - var shareBar = document.createElement("div"), - shareBarHelpID = parentID + "shareBarHelp", - shareButtonsDivID = parentID + "shareButtonsDiv", - showShareButtonsButtonDivID = parentID + "showShareButtonsButtonDiv", - showShareButtonsDotsID = parentID + "showShareButtonsDots", - showShareButtonsLabelID = parentID + "showShareButtonsLabel", - blastToConnectionsButtonID = parentID + "blastToConnectionsButton", - shareWithEveryoneButtonID = parentID + "shareWithEveryoneButton", - facebookButtonID = parentID + "facebookButton", - twitterButtonID = parentID + "twitterButton", - shareBarInnerHTML = ''; - - shareBar.id = parentID + "shareBar"; - shareBar.className = "shareControls"; - - if (isLoggedIn) { - if (canShare) { - shareBarInnerHTML = '' + - '
' + - '' + - '' + - '' + - '
' + - '' + - ''; - - // Add onclick handler to parent DIV's img to toggle share buttons - document.getElementById(parentID + 'img').onclick = function () { selectImageToShare(parentID, true); }; - } else { - shareBarInnerHTML = '
' + - '' + - '' + - '' + - '
' + - '' + - ''; - // Add onclick handler to parent DIV's img to toggle share buttons - document.getElementById(parentID + 'img').onclick = function () { selectImageWithHelpText(parentID, true); }; - } - } else { - shareBarInnerHTML = '
' + - '' + - '' + - '' + - '
' + - '' + - ''; - // Add onclick handler to parent DIV's img to toggle share buttons - document.getElementById(parentID + 'img').onclick = function () { selectImageWithHelpText(parentID, true); }; - } - - shareBar.innerHTML = shareBarInnerHTML; - - return shareBar; -} -function appendShareBar(divID, isLoggedIn, canShare, isGif, blastButtonDisabled, hifiButtonDisabled, canBlast) { - if (divID.id) { - divID = divID.id; // sometimes (?), `containerID` is passed as an HTML object to these functions; we just want the ID - } - document.getElementById(divID).appendChild(createShareBar(divID, isLoggedIn, canShare, isGif, blastButtonDisabled, hifiButtonDisabled, canBlast)); - if (divID === "p0") { - if (isLoggedIn) { - if (canShare) { - selectImageToShare(divID, true); - } else { - selectImageWithHelpText(divID, true); - } - } else { - selectImageWithHelpText(divID, true); - } - } - if (isLoggedIn && canShare) { - if (canBlast) { - shareButtonHovered('blast', divID, false); - } else { - shareButtonHovered('hifi', divID, false); - } - } -} -function shareForUrl(selectedID) { - EventBridge.emitWebEvent(JSON.stringify({ - type: "snapshot", - action: "shareSnapshotForUrl", - data: paths[parseInt(selectedID.substring(1), 10)] - })); -} -function addImage(image_data, isLoggedIn, canShare, isGifLoading, isShowingPreviousImages, blastButtonDisabled, hifiButtonDisabled, canBlast) { - if (!image_data.localPath) { - return; - } - var imageContainer = document.createElement("DIV"), - img = document.createElement("IMG"), - isGif = fileExtensionMatches(image_data.localPath, "gif"), - id = "p" + (isGif ? "1" : "0"); - imageContainer.id = id; - imageContainer.style.width = "95%"; - imageContainer.style.height = "240px"; - imageContainer.style.margin = "5px auto"; - imageContainer.style.display = "flex"; - imageContainer.style.justifyContent = "center"; - imageContainer.style.alignItems = "center"; - imageContainer.style.position = "relative"; - img.id = id + "img"; - img.src = image_data.localPath; - imageContainer.appendChild(img); - document.getElementById("snapshot-images").appendChild(imageContainer); - paths.push(image_data.localPath); - img.onload = function () { - if (isGif) { - imageContainer.innerHTML += 'GIF'; - } - if (!isGifLoading) { - appendShareBar(id, isLoggedIn, canShare, isGif, blastButtonDisabled, hifiButtonDisabled, canBlast); - } - if ((!isShowingPreviousImages && ((isGif && !isGifLoading) || !isGif)) || (isShowingPreviousImages && !image_data.story_id)) { - shareForUrl(id); - } - if (isShowingPreviousImages && isLoggedIn && image_data.story_id) { - updateShareInfo(id, image_data.story_id); - } - if (isShowingPreviousImages) { - requestPrintButtonUpdate(); - } - }; - img.onerror = function () { - img.onload = null; - img.src = image_data.errorPath; - EventBridge.emitWebEvent(JSON.stringify({ - type: "snapshot", - action: "alertSnapshotLoadFailed" - })); - }; -} -function showConfirmationMessage(selectedID, destination) { - if (selectedID.id) { - selectedID = selectedID.id; // sometimes (?), `containerID` is passed as an HTML object to these functions; we just want the ID - } - - var opacity = 2.0, - fadeRate = 0.05, - timeBetweenFadesMS = 50, - confirmationMessageContainer = document.createElement("div"), - confirmationMessage = document.createElement("div"); - confirmationMessageContainer.className = "confirmationMessageContainer"; - - confirmationMessage.className = "confirmationMessage"; - - var socialIcon = document.createElement("img"); - switch (destination) { - case 'blast': - socialIcon.src = "img/blast_icon.svg"; - confirmationMessage.appendChild(socialIcon); - confirmationMessage.innerHTML += 'Blast Sent!'; - confirmationMessage.style.backgroundColor = "#EA4C5F"; - break; - case 'hifi': - socialIcon.src = "img/hifi_icon.svg"; - confirmationMessage.appendChild(socialIcon); - confirmationMessage.innerHTML += 'Snap Shared!'; - confirmationMessage.style.backgroundColor = "#1FC6A6"; - break; - } - - confirmationMessageContainer.appendChild(confirmationMessage); - document.getElementById(selectedID).appendChild(confirmationMessageContainer); - - setInterval(function () { - if (opacity <= fadeRate) { - confirmationMessageContainer.remove(); - } - opacity -= fadeRate; - confirmationMessageContainer.style.opacity = opacity; - }, timeBetweenFadesMS); -} -function showUploadingMessage(selectedID, destination) { - if (selectedID.id) { - selectedID = selectedID.id; // sometimes (?), `containerID` is passed as an HTML object to these functions; we just want the ID - } - - var shareBarHelp = document.getElementById(selectedID + "shareBarHelp"); - - shareBarHelp.innerHTML = 'Preparing to Share'; - shareBarHelp.classList.add("uploading"); - shareBarHelp.setAttribute("data-destination", destination); -} -function hideUploadingMessageAndMaybeShare(selectedID, storyID) { - if (selectedID.id) { - selectedID = selectedID.id; // sometimes (?), `containerID` is passed as an HTML object to these functions; we just want the ID - } - - var shareBarHelp = document.getElementById(selectedID + "shareBarHelp"), - shareBarHelpDestination = shareBarHelp.getAttribute("data-destination"); - - shareBarHelp.classList.remove("uploading"); - if (shareBarHelpDestination) { - switch (shareBarHelpDestination) { - case 'blast': - blastToConnections(selectedID, selectedID === "p1"); - shareBarHelp.innerHTML = blastAlreadySharedText; - break; - case 'hifi': - shareWithEveryone(selectedID, selectedID === "p1"); - shareBarHelp.innerHTML = hifiAlreadySharedText; - break; - case 'facebook': - var facebookButton = document.getElementById(selectedID + "facebookButton"); - window.open(facebookButton.getAttribute("href"), "_blank"); - shareBarHelp.innerHTML = facebookShareText; - // This emitWebEvent() call isn't necessary in the "hifi" and "blast" cases - // because the "removeFromStoryIDsToMaybeDelete()" call happens - // in snapshot.js when sharing with that method. - EventBridge.emitWebEvent(JSON.stringify({ - type: "snapshot", - action: "removeFromStoryIDsToMaybeDelete", - story_id: storyID - })); - break; - case 'twitter': - var twitterButton = document.getElementById(selectedID + "twitterButton"); - window.open(twitterButton.getAttribute("href"), "_blank"); - shareBarHelp.innerHTML = twitterShareText; - EventBridge.emitWebEvent(JSON.stringify({ - type: "snapshot", - action: "removeFromStoryIDsToMaybeDelete", - story_id: storyID - })); - break; - } - - shareBarHelp.setAttribute("data-destination", ""); - } -} -function updateShareInfo(containerID, storyID) { - if (containerID.id) { - containerID = containerID.id; // sometimes (?), `containerID` is passed as an HTML object to these functions; we just want the ID - } - var shareBar = document.getElementById(containerID + "shareBar"), - parentDiv = document.getElementById(containerID), - shareURL = "https://highfidelity.com/user_stories/" + storyID, - facebookButton = document.getElementById(containerID + "facebookButton"), - twitterButton = document.getElementById(containerID + "twitterButton"); - - parentDiv.setAttribute('data-story-id', storyID); - - facebookButton.setAttribute("target", "_blank"); - facebookButton.setAttribute("href", 'https://www.facebook.com/dialog/feed?app_id=1585088821786423&link=' + shareURL); - - twitterButton.setAttribute("target", "_blank"); - twitterButton.setAttribute("href", 'https://twitter.com/intent/tweet?text=I%20just%20took%20a%20snapshot!&url=' + shareURL + '&via=highfidelityVR&hashtags=VR,HiFi'); - - hideUploadingMessageAndMaybeShare(containerID, storyID); -} -function blastToConnections(selectedID, isGif) { - if (selectedID.id) { - selectedID = selectedID.id; // sometimes (?), `selectedID` is passed as an HTML object to these functions; we just want the ID - } - - var blastToConnectionsButton = document.getElementById(selectedID + "blastToConnectionsButton"), - shareBar = document.getElementById(selectedID + "shareBar"), - shareBarHelp = document.getElementById(selectedID + "shareBarHelp"); - blastToConnectionsButton.onclick = function () { }; - - var storyID = document.getElementById(selectedID).getAttribute("data-story-id"); - - if (storyID) { - EventBridge.emitWebEvent(JSON.stringify({ - type: "snapshot", - action: "blastToConnections", - story_id: storyID, - isGif: isGif - })); - showConfirmationMessage(selectedID, 'blast'); - blastToConnectionsButton.classList.add("disabled"); - blastToConnectionsButton.style.backgroundColor = "#000000"; - blastToConnectionsButton.style.opacity = "0.5"; - shareBarHelp.style.backgroundColor = "#000000"; - shareBarHelp.style.opacity = "0.5"; - } else { - showUploadingMessage(selectedID, 'blast'); - } -} -function shareWithEveryone(selectedID, isGif) { - if (selectedID.id) { - selectedID = selectedID.id; // sometimes (?), `selectedID` is passed as an HTML object to these functions; we just want the ID - } - - var shareWithEveryoneButton = document.getElementById(selectedID + "shareWithEveryoneButton"), - shareBar = document.getElementById(selectedID + "shareBar"), - shareBarHelp = document.getElementById(selectedID + "shareBarHelp"); - shareWithEveryoneButton.onclick = function () { }; - - var storyID = document.getElementById(selectedID).getAttribute("data-story-id"); - - if (storyID) { - EventBridge.emitWebEvent(JSON.stringify({ - type: "snapshot", - action: "shareSnapshotWithEveryone", - story_id: storyID, - isGif: isGif - })); - showConfirmationMessage(selectedID, 'hifi'); - shareWithEveryoneButton.classList.add("disabled"); - shareWithEveryoneButton.style.backgroundColor = "#000000"; - shareWithEveryoneButton.style.opacity = "0.5"; - shareBarHelp.style.backgroundColor = "#000000"; - shareBarHelp.style.opacity = "0.5"; - } else { - showUploadingMessage(selectedID, 'hifi'); - } -} -function shareButtonHovered(destination, selectedID, shouldAlsoModifyOther) { - if (selectedID.id) { - selectedID = selectedID.id; // sometimes (?), `selectedID` is passed as an HTML object to these functions; we just want the ID - } - var shareBarHelp = document.getElementById(selectedID + "shareBarHelp"), - shareButtonsDiv = document.getElementById(selectedID + "shareButtonsDiv").childNodes, - itr; - - if (!shareBarHelp.classList.contains("uploading")) { - for (itr = 0; itr < shareButtonsDiv.length; itr += 1) { - shareButtonsDiv[itr].style.backgroundColor = "rgba(0, 0, 0, 0)"; - } - shareBarHelp.style.opacity = "1.0"; - switch (destination) { - case 'blast': - var blastToConnectionsButton = document.getElementById(selectedID + "blastToConnectionsButton"); - if (!blastToConnectionsButton.classList.contains("disabled")) { - shareBarHelp.style.backgroundColor = "#EA4C5F"; - shareBarHelp.style.opacity = "1.0"; - blastToConnectionsButton.style.backgroundColor = "#EA4C5F"; - blastToConnectionsButton.style.opacity = "1.0"; - shareBarHelp.innerHTML = blastShareText; - } else { - shareBarHelp.style.backgroundColor = "#000000"; - shareBarHelp.style.opacity = "0.5"; - blastToConnectionsButton.style.backgroundColor = "#000000"; - blastToConnectionsButton.style.opacity = "0.5"; - shareBarHelp.innerHTML = blastAlreadySharedText; - } - break; - case 'hifi': - var shareWithEveryoneButton = document.getElementById(selectedID + "shareWithEveryoneButton"); - if (!shareWithEveryoneButton.classList.contains("disabled")) { - shareBarHelp.style.backgroundColor = "#1FC6A6"; - shareBarHelp.style.opacity = "1.0"; - shareWithEveryoneButton.style.backgroundColor = "#1FC6A6"; - shareWithEveryoneButton.style.opacity = "1.0"; - shareBarHelp.innerHTML = hifiShareText; - } else { - shareBarHelp.style.backgroundColor = "#000000"; - shareBarHelp.style.opacity = "0.5"; - shareWithEveryoneButton.style.backgroundColor = "#000000"; - shareWithEveryoneButton.style.opacity = "0.5"; - shareBarHelp.innerHTML = hifiAlreadySharedText; - } - break; - case 'facebook': - shareBarHelp.style.backgroundColor = "#3C58A0"; - shareBarHelp.innerHTML = facebookShareText; - document.getElementById(selectedID + "facebookButton").style.backgroundColor = "#3C58A0"; - break; - case 'twitter': - shareBarHelp.style.backgroundColor = "#00B4EE"; - shareBarHelp.innerHTML = twitterShareText; - document.getElementById(selectedID + "twitterButton").style.backgroundColor = "#00B4EE"; - break; - } - } - - if (shouldAlsoModifyOther && imageCount > 1) { - if (selectedID === "p0" && !document.getElementById("p1").classList.contains("processingGif")) { - shareButtonHovered(destination, "p1", false); - } else if (selectedID === "p1") { - shareButtonHovered(destination, "p0", false); - } - } -} -function shareButtonClicked(destination, selectedID) { - if (selectedID.id) { - selectedID = selectedID.id; // sometimes (?), `selectedID` is passed as an HTML object to these functions; we just want the ID - } - var storyID = document.getElementById(selectedID).getAttribute("data-story-id"); - - if (!storyID) { - showUploadingMessage(selectedID, destination); - } else { - EventBridge.emitWebEvent(JSON.stringify({ - type: "snapshot", - action: "removeFromStoryIDsToMaybeDelete", - story_id: storyID - })); - } -} - -function handleCaptureSetting(setting) { - var stillAndGif = document.getElementById('stillAndGif'), - stillOnly = document.getElementById('stillOnly'); - - stillAndGif.checked = setting; - stillOnly.checked = !setting; - - stillAndGif.onclick = function () { - EventBridge.emitWebEvent(JSON.stringify({ - type: "snapshot", - action: "captureStillAndGif" - })); - }; - - stillOnly.onclick = function () { - EventBridge.emitWebEvent(JSON.stringify({ - type: "snapshot", - action: "captureStillOnly" - })); - }; - -} -window.onload = function () { - // Uncomment the line below to test functionality in a browser. - // See definition of "testInBrowser()" to modify tests. - //testInBrowser(4); - openEventBridge(function () { - // Set up a handler for receiving the data, and tell the .js we are ready to receive it. - EventBridge.scriptEventReceived.connect(function (message) { - - message = JSON.parse(message); - - if (message.type !== "snapshot") { - return; - } - - var messageOptions = message.options; - - switch (message.action) { - case 'showSetupInstructions': - showSetupInstructions(); - break; - case 'snapshotLocationChosen': - clearImages(); - showSetupComplete(); - break; - case 'clearPreviousImages': - clearImages(); - break; - case 'showPreviousImages': - clearImages(); - imageCount = message.image_data.length; - if (imageCount > 0) { - message.image_data.forEach(function (element, idx) { - addImage(element, messageOptions.isLoggedIn, message.canShare, false, true, message.image_data[idx].blastButtonDisabled, message.image_data[idx].hifiButtonDisabled, messageOptions.canBlast); - }); - } else { - showSnapshotInstructions(); - } - break; - case 'addImages': - // The last element of the message contents list contains a bunch of options, - // including whether or not we can share stuff - // The other elements of the list contain image paths. - if (messageOptions.containsGif === true) { - if (messageOptions.processingGif === true) { - imageCount = message.image_data.length + 1; // "+1" for the GIF that'll finish processing soon - message.image_data.push({ localPath: messageOptions.loadingGifPath }); - message.image_data.forEach(function (element, idx) { - addImage(element, messageOptions.isLoggedIn, idx === 0 && messageOptions.canShare, idx === 1, false, false, false, true); - }); - document.getElementById("p1").classList.add("processingGif"); - document.getElementById("snap-button").disabled = true; - } else { - var gifPath = message.image_data[0].localPath, - p1img = document.getElementById('p1img'); - p1img.src = gifPath; - - paths[1] = gifPath; - shareForUrl("p1"); - appendShareBar("p1", messageOptions.isLoggedIn, messageOptions.canShare, true, false, false, messageOptions.canBlast); - document.getElementById("p1").classList.remove("processingGif"); - document.getElementById("snap-button").disabled = false; - } - } else { - imageCount = message.image_data.length; - message.image_data.forEach(function (element) { - addImage(element, messageOptions.isLoggedIn, messageOptions.canShare, false, false, false, false, true); - }); - document.getElementById("snap-button").disabled = false; - } - break; - case 'captureSettings': - handleCaptureSetting(message.setting); - break; - case 'setPrintButtonEnabled': - setPrintButtonEnabled(); - break; - case 'setPrintButtonLoading': - setPrintButtonLoading(); - break; - case 'setPrintButtonDisabled': - setPrintButtonDisabled(); - break; - case 'snapshotUploadComplete': - var isGif = fileExtensionMatches(message.image_url, "gif"); - updateShareInfo(isGif ? "p1" : "p0", message.story_id); - if (isPrintProcessing()) { - setPrintButtonEnabled(); - } - break; - default: - console.log("Unknown message action received in SnapshotReview.js."); - break; - } - }); - - EventBridge.emitWebEvent(JSON.stringify({ - type: "snapshot", - action: "ready" - })); - });; -}; -function snapshotSettings() { - EventBridge.emitWebEvent(JSON.stringify({ - type: "snapshot", - action: "openSettings" - })); -} -function takeSnapshot() { - document.getElementById("snap-button").disabled = true; - EventBridge.emitWebEvent(JSON.stringify({ - type: "snapshot", - action: "takeSnapshot" - })); -} - -function isPrintDisabled() { - var printElement = document.getElementById('print-icon'); - - return printElement.classList.contains("print-icon") && - printElement.classList.contains("print-icon-default") && - document.getElementById('print-button').disabled; -} -function isPrintProcessing() { - var printElement = document.getElementById('print-icon'); - - return printElement.classList.contains("print-icon") && - printElement.classList.contains("print-icon-loading") && - document.getElementById('print-button').disabled; -} -function isPrintEnabled() { - var printElement = document.getElementById('print-icon'); - - return printElement.classList.contains("print-icon") && - printElement.classList.contains("print-icon-default") && - !document.getElementById('print-button').disabled; -} - -function setPrintButtonLoading() { - document.getElementById('print-icon').className = "print-icon print-icon-loading"; - document.getElementById('print-button').disabled = true; -} -function setPrintButtonDisabled() { - document.getElementById('print-icon').className = "print-icon print-icon-default"; - document.getElementById('print-button').disabled = true; -} -function setPrintButtonEnabled() { - document.getElementById('print-button').disabled = false; - document.getElementById('print-icon').className = "print-icon print-icon-default"; -} - -function requestPrintButtonUpdate() { - EventBridge.emitWebEvent(JSON.stringify({ - type: "snapshot", - action: "requestPrintButtonUpdate" - })); -} - -function printToPolaroid() { - if (isPrintEnabled()) { - EventBridge.emitWebEvent(JSON.stringify({ - type: "snapshot", - action: "printToPolaroid" - })); - } else { - setPrintButtonLoading(); - } -} - -function testInBrowser(test) { - if (test === 0) { - showSetupInstructions(); - } else if (test === 1) { - imageCount = 2; - //addImage({ localPath: 'http://lorempixel.com/553/255' }); - addImage({ localPath: 'D:/Dropbox/Screenshots/High Fidelity Snapshots/hifi-snap-by-zfox-on-2017-05-01_13-28-58.jpg', story_id: 1338 }, true, true, false, true, false, false, true); - addImage({ localPath: 'D:/Dropbox/Screenshots/High Fidelity Snapshots/hifi-snap-by-zfox-on-2017-05-01_13-28-58.gif', story_id: 1337 }, true, true, false, true, false, false, true); - } else if (test === 2) { - addImage({ localPath: 'D:/Dropbox/Screenshots/High Fidelity Snapshots/hifi-snap-by-zfox-on-2017-05-01_13-28-58.jpg', story_id: 1338 }, true, true, false, true, false, false, true); - addImage({ localPath: 'D:/Dropbox/Screenshots/High Fidelity Snapshots/hifi-snap-by-zfox-on-2017-05-01_13-28-58.gif', story_id: 1337 }, true, true, false, true, false, false, true); - showConfirmationMessage("p0", 'blast'); - showConfirmationMessage("p1", 'hifi'); - } else if (test === 3) { - imageCount = 2; - //addImage({ localPath: 'http://lorempixel.com/553/255' }); - addImage({ localPath: 'D:/Dropbox/Screenshots/High Fidelity Snapshots/hifi-snap-by-zfox-on-2017-05-01_13-28-58.jpg', story_id: 1338 }, true, true, false, true, false, false, true); - addImage({ localPath: 'D:/Dropbox/Screenshots/High Fidelity Snapshots/hifi-snap-by-zfox-on-2017-05-01_13-28-58.gif', story_id: 1337 }, true, true, false, true, false, false, true); - showUploadingMessage("p0", 'hifi'); - } else if (test === 4) { - imageCount = 2; - //addImage({ localPath: 'http://lorempixel.com/553/255' }); - addImage({ localPath: 'D:/Dropbox/Screenshots/High Fidelity Snapshots/hifi-snap-by-zfox-on-2017-05-01_13-28-58.jpg', story_id: 1338 }, false, true, false, true, false, false, true); - addImage({ localPath: 'D:/Dropbox/Screenshots/High Fidelity Snapshots/hifi-snap-by-zfox-on-2017-05-01_13-28-58.gif', story_id: 1337 }, false, true, false, true, false, false, true); -} -} diff --git a/scripts/simplifiedUI/system/html/js/colpick.js b/scripts/simplifiedUI/system/html/js/colpick.js deleted file mode 100644 index e4ad65dfb6..0000000000 --- a/scripts/simplifiedUI/system/html/js/colpick.js +++ /dev/null @@ -1,616 +0,0 @@ -/* -colpick Color Picker -Copyright 2013 Jose Vargas. Licensed under GPL license. Based on Stefan Petre's Color Picker www.eyecon.ro, dual licensed -under the MIT and GPL licenses - -For usage and examples: colpick.com/plugin - */ - -/* global console, document, Element, EventBridge, jQuery, navigator, window, _ $ */ - -(function ($) { - var colpick = function () { - var - tpl = '
' + - '
' + - '
' + - '
' + - '
' + - '
#
' + - '
' + - '
R
' + - '
' + - '
' + - '
G
' + - '
' + - '
B
' + - '
' + - '
' + - '
H
' + - '
' + - '
' + - '
S
' + - '
' + - '
' + - '
B
' + - '
' + - '
' + - '
', - defaults = { - showEvent: 'click', - onShow: function () {}, - onBeforeShow: function(){}, - onHide: function () {}, - onChange: function () {}, - onSubmit: function () {}, - colorScheme: 'light', - color: '3289c7', - livePreview: true, - flat: false, - layout: 'full', - submit: 1, - submitText: 'OK', - height: 156 - }, - // Fill the inputs of the plugin - fillRGBFields = function (hsb, cal) { - var rgb = hsbToRgb(hsb); - $(cal).data('colpick').fields - .eq(1).val(rgb.r).end() - .eq(2).val(rgb.g).end() - .eq(3).val(rgb.b).end(); - }, - fillHSBFields = function (hsb, cal) { - $(cal).data('colpick').fields - .eq(4).val(Math.round(hsb.h)).end() - .eq(5).val(Math.round(hsb.s)).end() - .eq(6).val(Math.round(hsb.b)).end(); - }, - fillHexFields = function (hsb, cal) { - $(cal).data('colpick').fields.eq(0).val(hsbToHex(hsb)); - }, - // Set the round selector position - setSelector = function (hsb, cal) { - $(cal).data('colpick').selector.css('backgroundColor', '#' + hsbToHex({h: hsb.h, s: 100, b: 100})); - $(cal).data('colpick').selectorIndic.css({ - left: parseInt($(cal).data('colpick').height * hsb.s/100, 10), - top: parseInt($(cal).data('colpick').height * (100-hsb.b)/100, 10) - }); - }, - // Set the hue selector position - setHue = function (hsb, cal) { - $(cal).data('colpick').hue.css('top', - parseInt($(cal).data('colpick').height - $(cal).data('colpick').height * hsb.h / 360, 10)); - }, - // Set current and new colors - setCurrentColor = function (hsb, cal) { - $(cal).data('colpick').currentColor.css('backgroundColor', '#' + hsbToHex(hsb)); - }, - setNewColor = function (hsb, cal) { - $(cal).data('colpick').newColor.css('backgroundColor', '#' + hsbToHex(hsb)); - }, - // Called when the new color is changed - change = function (ev) { - var cal = $(this).parent().parent(), col; - if (this.parentNode.className.indexOf('_hex') > 0) { - cal.data('colpick').color = col = hexToHsb(fixHex(this.value)); - fillRGBFields(col, cal.get(0)); - fillHSBFields(col, cal.get(0)); - fillHexFields(col, cal.get(0)); - } else if (this.parentNode.className.indexOf('_hsb') > 0) { - cal.data('colpick').color = col = fixHSB({ - h: parseInt(cal.data('colpick').fields.eq(4).val(), 10), - s: parseInt(cal.data('colpick').fields.eq(5).val(), 10), - b: parseInt(cal.data('colpick').fields.eq(6).val(), 10) - }); - fillRGBFields(col, cal.get(0)); - fillHexFields(col, cal.get(0)); - fillHSBFields(col, cal.get(0)); - } else { - cal.data('colpick').color = col = rgbToHsb(fixRGB({ - r: parseInt(cal.data('colpick').fields.eq(1).val(), 10), - g: parseInt(cal.data('colpick').fields.eq(2).val(), 10), - b: parseInt(cal.data('colpick').fields.eq(3).val(), 10) - })); - fillHexFields(col, cal.get(0)); - fillHSBFields(col, cal.get(0)); - fillRGBFields(col, cal.get(0)); - } - setSelector(col, cal.get(0)); - setHue(col, cal.get(0)); - setNewColor(col, cal.get(0)); - cal.data('colpick').onChange.apply(cal.parent(), - [col, hsbToHex(col), hsbToRgb(col), cal.data('colpick').el, 0]); - }, - // Change style on blur and on focus of inputs - blur = function (ev) { - $(this).parent().removeClass('colpick_focus'); - }, - focus = function () { - $(this).parent().parent().data('colpick').fields.parent().removeClass('colpick_focus'); - $(this).parent().addClass('colpick_focus'); - }, - // Increment/decrement arrows functions - downIncrement = function (ev) { - ev.preventDefault ? ev.preventDefault() : ev.returnValue = false; - var field = $(this).parent().find('input').focus(); - var current = { - el: $(this).parent().addClass('colpick_slider'), - max: this.parentNode.className.indexOf('_hsb_h') > 0 ? 360 : - (this.parentNode.className.indexOf('_hsb') > 0 ? 100 : 255), - y: ev.pageY, - field: field, - val: parseInt(field.val(), 10), - preview: $(this).parent().parent().data('colpick').livePreview - }; - $(document).mouseup(current, upIncrement); - $(document).mousemove(current, moveIncrement); - }, - moveIncrement = function (ev) { - ev.data.field.val(Math.max(0, Math.min(ev.data.max, parseInt(ev.data.val - ev.pageY + ev.data.y, 10)))); - if (ev.data.preview) { - change.apply(ev.data.field.get(0), [true]); - } - return false; - }, - upIncrement = function (ev) { - change.apply(ev.data.field.get(0), [true]); - ev.data.el.removeClass('colpick_slider').find('input').focus(); - $(document).off('mouseup', upIncrement); - $(document).off('mousemove', moveIncrement); - return false; - }, - // Hue slider functions - downHue = function (ev) { - ev.preventDefault ? ev.preventDefault() : ev.returnValue = false; - var current = { - cal: $(this).parent(), - y: $(this).offset().top - }; - $(document).on('mouseup touchend',current,upHue); - $(document).on('mousemove touchmove',current,moveHue); - - var pageY = ((ev.type === 'touchstart') ? ev.originalEvent.changedTouches[0].pageY : ev.pageY ); - change.apply( - current.cal.data('colpick') - .fields.eq(4).val(parseInt(360 * (current.cal.data('colpick').height - - (pageY - current.y)) / current.cal.data('colpick').height, 10)) - .get(0), - [current.cal.data('colpick').livePreview] - ); - return false; - }, - moveHue = function (ev) { - var pageY = ((ev.type === 'touchmove') ? ev.originalEvent.changedTouches[0].pageY : ev.pageY ); - change.apply( - ev.data.cal.data('colpick') - .fields.eq(4).val(parseInt(360 * (ev.data.cal.data('colpick').height - - Math.max(0, Math.min(ev.data.cal.data('colpick').height, (pageY - ev.data.y)))) / - ev.data.cal.data('colpick').height, 10)) - .get(0), - [ev.data.preview] - ); - return false; - }, - upHue = function (ev) { - fillRGBFields(ev.data.cal.data('colpick').color, ev.data.cal.get(0)); - fillHexFields(ev.data.cal.data('colpick').color, ev.data.cal.get(0)); - $(document).off('mouseup touchend',upHue); - $(document).off('mousemove touchmove',moveHue); - return false; - }, - // Color selector functions - downSelector = function (ev) { - ev.preventDefault ? ev.preventDefault() : ev.returnValue = false; - var current = { - cal: $(this).parent(), - pos: $(this).offset() - }; - current.preview = current.cal.data('colpick').livePreview; - - $(document).on('mouseup touchend',current,upSelector); - $(document).on('mousemove touchmove',current,moveSelector); - - var pageX,pageY; - if (ev.type === 'touchstart') { - pageX = ev.originalEvent.changedTouches[0].pageX, - pageY = ev.originalEvent.changedTouches[0].pageY; - } else { - pageX = ev.pageX; - pageY = ev.pageY; - } - - change.apply( - current.cal.data('colpick').fields - .eq(6).val(parseInt(100 * (current.cal.data('colpick').height - (pageY - current.pos.top)) / - current.cal.data('colpick').height, 10)).end() - .eq(5).val(parseInt(100*(pageX - current.pos.left)/current.cal.data('colpick').height, 10)) - .get(0), - [current.preview] - ); - return false; - }, - moveSelector = function (ev) { - var pageX,pageY; - if (ev.type === 'touchmove') { - pageX = ev.originalEvent.changedTouches[0].pageX, - pageY = ev.originalEvent.changedTouches[0].pageY; - } else { - pageX = ev.pageX; - pageY = ev.pageY; - } - - change.apply( - ev.data.cal.data('colpick').fields - .eq(6).val(parseInt(100 * (ev.data.cal.data('colpick').height - - Math.max(0, Math.min(ev.data.cal.data('colpick').height, (pageY - ev.data.pos.top)))) / - ev.data.cal.data('colpick').height, 10)).end() - .eq(5).val(parseInt(100 * (Math.max(0, Math.min(ev.data.cal.data('colpick').height, - (pageX - ev.data.pos.left)))) / ev.data.cal.data('colpick').height, 10)) - .get(0), - [ev.data.preview] - ); - return false; - }, - upSelector = function (ev) { - fillRGBFields(ev.data.cal.data('colpick').color, ev.data.cal.get(0)); - fillHexFields(ev.data.cal.data('colpick').color, ev.data.cal.get(0)); - $(document).off('mouseup touchend',upSelector); - $(document).off('mousemove touchmove',moveSelector); - return false; - }, - // Submit button - clickSubmit = function (ev) { - var cal = $(this).parent(); - var col = cal.data('colpick').color; - cal.data('colpick').origColor = col; - setCurrentColor(col, cal.get(0)); - cal.data('colpick').onSubmit(col, hsbToHex(col), hsbToRgb(col), cal.data('colpick').el); - }, - // Show/hide the color picker - show = function (ev) { - if ($(this).attr('disabled')) { - return; - } - // Prevent the trigger of any direct parent - ev.stopPropagation(); - var cal = $('#' + $(this).data('colpickId')); - cal.data('colpick').onBeforeShow.apply(this, [cal.get(0)]); - var pos = $(this).offset(); - var top = pos.top + this.offsetHeight; - var left = pos.left; - var viewPort = getViewport(); - var calW = cal.width(); - if (left + calW > viewPort.l + viewPort.w) { - left -= calW; - } - cal.css({left: left + 'px', top: top + 'px'}); - if (cal.data('colpick').onShow.apply(this, [cal.get(0)]) !== false) { - cal.show(); - } - // Hide when user clicks outside - $('html').mousedown({cal:cal}, hide); - cal.mousedown(function(ev){ - ev.stopPropagation(); - }); - }, - hide = function (ev) { - if (ev.data.cal.data('colpick').onHide.apply(this, [ev.data.cal.get(0)]) !== false) { - ev.data.cal.hide(); - } - $('html').off('mousedown', hide); - }, - getViewport = function () { - var m = document.compatMode === 'CSS1Compat'; - return { - l : window.pageXOffset || (m ? document.documentElement.scrollLeft : document.body.scrollLeft), - w : window.innerWidth || (m ? document.documentElement.clientWidth : document.body.clientWidth) - }; - }, - // Fix the values if the user enters a negative or high value - fixHSB = function (hsb) { - hsb.h = isNaN(hsb.h) ? 0 : hsb.h; - hsb.s = isNaN(hsb.s) ? 0 : hsb.s; - hsb.b = isNaN(hsb.b) ? 0 : hsb.b; - return { - h: Math.min(360, Math.max(0, hsb.h)), - s: Math.min(100, Math.max(0, hsb.s)), - b: Math.min(100, Math.max(0, hsb.b)) - }; - }, - fixRGB = function (rgb) { - rgb.r = isNaN(rgb.r) ? 0 : rgb.r; - rgb.g = isNaN(rgb.g) ? 0 : rgb.g; - rgb.b = isNaN(rgb.b) ? 0 : rgb.b; - return { - r: Math.min(255, Math.max(0, rgb.r)), - g: Math.min(255, Math.max(0, rgb.g)), - b: Math.min(255, Math.max(0, rgb.b)) - }; - }, - fixHex = function (hex) { - var len = 6 - hex.length; - if (len > 0) { - var o = []; - for (var i=0; i').attr('style', - 'height:8.333333%; filter:progid:' + - 'DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr=' + stops[i] + - ', endColorstr=' + stops[i + 1] + - '); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr=' + - stops[i] + ', endColorstr=' + stops[i + 1] + ')";'); - huebar.append(div); - } - } else { - var stopList = stops.join(','); - huebar.attr('style', 'background:-webkit-linear-gradient(top,' + stopList + - '); background: -o-linear-gradient(top,' + stopList + - '); background: -ms-linear-gradient(top,' + stopList + - '); background:-moz-linear-gradient(top,' + stopList + - '); -webkit-linear-gradient(top,' + stopList + - '); background:linear-gradient(to bottom,' + stopList + '); '); - } - cal.find('div.colpick_hue').on('mousedown touchstart',downHue); - options.newColor = cal.find('div.colpick_new_color'); - options.currentColor = cal.find('div.colpick_current_color'); - // Store options and fill with default color - cal.data('colpick', options); - fillRGBFields(options.color, cal.get(0)); - fillHSBFields(options.color, cal.get(0)); - fillHexFields(options.color, cal.get(0)); - setHue(options.color, cal.get(0)); - setSelector(options.color, cal.get(0)); - setCurrentColor(options.color, cal.get(0)); - setNewColor(options.color, cal.get(0)); - // Append to body if flat=false, else show in place - if (options.flat) { - cal.appendTo(this).show(); - cal.css({ - position: 'relative', - display: 'block' - }); - } else { - cal.appendTo(document.body); - $(this).on(options.showEvent, show); - cal.css({ - position:'absolute' - }); - } - } - }); - }, - // Shows the picker - showPicker: function() { - return this.each( function () { - if ($(this).data('colpickId')) { - show.apply(this); - } - }); - }, - // Hides the picker - hidePicker: function() { - return this.each( function () { - if ($(this).data('colpickId')) { - $('#' + $(this).data('colpickId')).hide(); - } - }); - }, - // Sets a color as new and current (default) - setColor: function(col, setCurrent) { - setCurrent = (typeof setCurrent === "undefined") ? 1 : setCurrent; - if (typeof col === 'string') { - col = hexToHsb(col); - } else if (col.r !== undefined && col.g !== undefined && col.b !== undefined) { - col = rgbToHsb(col); - } else if (col.h !== undefined && col.s !== undefined && col.b !== undefined) { - col = fixHSB(col); - } else { - return this; - } - return this.each(function(){ - if ($(this).data('colpickId')) { - var cal = $('#' + $(this).data('colpickId')); - cal.data('colpick').color = col; - cal.data('colpick').origColor = col; - fillRGBFields(col, cal.get(0)); - fillHSBFields(col, cal.get(0)); - fillHexFields(col, cal.get(0)); - setHue(col, cal.get(0)); - setSelector(col, cal.get(0)); - - setNewColor(col, cal.get(0)); - cal.data('colpick').onChange.apply(cal.parent(), - [col, hsbToHex(col), hsbToRgb(col), cal.data('colpick').el, 1]); - if (setCurrent) { - setCurrentColor(col, cal.get(0)); - } - } - }); - } - }; - }(); - // Color space convertions - var hexToRgb = function (hexString) { - if (typeof hexString !== "string") { - print("Error - ColPick.js::hexToRgb expects string object."); - return; - } - - var hexNumber = parseInt(((hexString.indexOf('#') > -1) ? hexString.substring(1) : hexString), 16); - return { r: hexNumber >> 16, g: (hexNumber & 0x00FF00) >> 8, b: (hexNumber & 0x0000FF)}; - }; - var hexToHsb = function (hexString) { - if (typeof hexString !== "string") { - print("Error - ColPick.js::hexToHsb expects string object."); - return; - } - - return rgbToHsb(hexToRgb(hexString)); - }; - var rgbToHsb = function (rgb) { - var hsb = {h: 0, s: 0, b: 0}; - var min = Math.min(rgb.r, rgb.g, rgb.b); - var max = Math.max(rgb.r, rgb.g, rgb.b); - var delta = max - min; - hsb.b = max; - hsb.s = max != 0 ? 255 * delta / max : 0; // eslint-disable-line eqeqeq - if (hsb.s != 0) { // eslint-disable-line eqeqeq - if (rgb.r == max) { // eslint-disable-line eqeqeq - hsb.h = (rgb.g - rgb.b) / delta; - } else if (rgb.g == max) { // eslint-disable-line eqeqeq - hsb.h = 2 + (rgb.b - rgb.r) / delta; - } else { - hsb.h = 4 + (rgb.r - rgb.g) / delta; - } - } else { - hsb.h = -1; - } - hsb.h *= 60; - if (hsb.h < 0) { - hsb.h += 360; - } - hsb.s *= 100/255; - hsb.b *= 100/255; - return hsb; - }; - var hsbToRgb = function (hsb) { - var rgb = {}; - var h = hsb.h; - var s = hsb.s*255/100; - var v = hsb.b*255/100; - if (s == 0) { // eslint-disable-line eqeqeq - rgb.r = rgb.g = rgb.b = v; - } else { - var t1 = v; - var t2 = (255-s)*v/255; - var t3 = (t1-t2)*(h%60)/60; - if (h==360) { // eslint-disable-line eqeqeq - h = 0; - } - if (h<60) { - rgb.r=t1; rgb.b=t2; rgb.g=t2+t3; - } else if (h<120) { - rgb.g=t1; rgb.b=t2; rgb.r=t1-t3; - } else if (h<180) { - rgb.g=t1; rgb.r=t2; rgb.b=t2+t3; - } else if (h<240) { - rgb.b=t1; rgb.r=t2; rgb.g=t1-t3; - } else if (h<300) { - rgb.b=t1; rgb.g=t2; rgb.r=t2+t3; - } else if (h<360) { - rgb.r=t1; rgb.g=t2; rgb.b=t1-t3; - } else { - rgb.r=0; rgb.g=0; rgb.b=0; - } - } - return {r:Math.round(rgb.r), g:Math.round(rgb.g), b:Math.round(rgb.b)}; - }; - var rgbToHex = function (rgb) { - var hex = [ - rgb.r.toString(16), - rgb.g.toString(16), - rgb.b.toString(16) - ]; - $.each(hex, function (nr, val) { - if (val.length == 1) { // eslint-disable-line eqeqeq - hex[nr] = '0' + val; - } - }); - return hex.join(''); - }; - var hsbToHex = function (hsb) { - return rgbToHex(hsbToRgb(hsb)); - }; - $.fn.extend({ - colpick: colpick.init, - colpickHide: colpick.hidePicker, - colpickShow: colpick.showPicker, - colpickSetColor: colpick.setColor - }); - $.extend({ - colpick:{ - rgbToHex: rgbToHex, - rgbToHsb: rgbToHsb, - hsbToHex: hsbToHex, - hsbToRgb: hsbToRgb, - hexToHsb: hexToHsb, - hexToRgb: hexToRgb - } - }); -})(jQuery); - diff --git a/scripts/simplifiedUI/system/html/js/entityProperties.js b/scripts/simplifiedUI/system/html/js/entityProperties.js deleted file mode 100644 index e64543d41f..0000000000 --- a/scripts/simplifiedUI/system/html/js/entityProperties.js +++ /dev/null @@ -1,4419 +0,0 @@ -// entityProperties.js -// -// Created by Ryan Huffman on 13 Nov 2014 -// Modified by David Back on 19 Oct 2018 -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - -/* global alert, augmentSpinButtons, clearTimeout, console, document, Element, - EventBridge, JSONEditor, openEventBridge, setTimeout, window, _, $ */ - -const DEGREES_TO_RADIANS = Math.PI / 180.0; - -const NO_SELECTION = ","; - -const PROPERTY_SPACE_MODE = Object.freeze({ - ALL: 0, - LOCAL: 1, - WORLD: 2 -}); - -const PROPERTY_SELECTION_VISIBILITY = Object.freeze({ - SINGLE_SELECTION: 1, - MULTIPLE_SELECTIONS: 2, - MULTI_DIFF_SELECTIONS: 4, - ANY_SELECTIONS: 7, /* SINGLE_SELECTION | MULTIPLE_SELECTIONS | MULTI_DIFF_SELECTIONS */ -}); - -// Multiple-selection behavior -const PROPERTY_MULTI_DISPLAY_MODE = Object.freeze({ - DEFAULT: 0, - /** - * Comma separated values - * Limited for properties with type "string" or "textarea" and readOnly enabled - */ - COMMA_SEPARATED_VALUES: 1, -}); - -const GROUPS = [ - { - id: "base", - properties: [ - { - label: NO_SELECTION, - type: "icon", - icons: ENTITY_TYPE_ICON, - propertyID: "type", - replaceID: "placeholder-property-type", - }, - { - label: "Name", - type: "string", - propertyID: "name", - placeholder: "Name", - replaceID: "placeholder-property-name", - }, - { - label: "ID", - type: "string", - propertyID: "id", - placeholder: "ID", - readOnly: true, - replaceID: "placeholder-property-id", - multiDisplayMode: PROPERTY_MULTI_DISPLAY_MODE.COMMA_SEPARATED_VALUES, - }, - { - label: "Description", - type: "string", - propertyID: "description", - }, - { - label: "Parent", - type: "string", - propertyID: "parentID", - onChange: parentIDChanged, - }, - { - label: "Parent Joint Index", - type: "number", - propertyID: "parentJointIndex", - }, - { - label: "", - glyph: "", - type: "bool", - propertyID: "locked", - replaceID: "placeholder-property-locked", - }, - { - label: "", - glyph: "", - type: "bool", - propertyID: "visible", - replaceID: "placeholder-property-visible", - }, - { - label: "Render Layer", - type: "dropdown", - options: { - world: "World", - front: "Front", - hud: "HUD" - }, - propertyID: "renderLayer", - }, - { - label: "Primitive Mode", - type: "dropdown", - options: { - solid: "Solid", - lines: "Wireframe", - }, - propertyID: "primitiveMode", - }, - ] - }, - { - id: "shape", - addToGroup: "base", - properties: [ - { - label: "Shape", - type: "dropdown", - options: { Cube: "Box", Sphere: "Sphere", Tetrahedron: "Tetrahedron", Octahedron: "Octahedron", - Icosahedron: "Icosahedron", Dodecahedron: "Dodecahedron", Hexagon: "Hexagon", - Triangle: "Triangle", Octagon: "Octagon", Cylinder: "Cylinder", Cone: "Cone", - Circle: "Circle", Quad: "Quad" }, - propertyID: "shape", - }, - { - label: "Color", - type: "color", - propertyID: "color", - }, - ] - }, - { - id: "text", - addToGroup: "base", - properties: [ - { - label: "Text", - type: "string", - propertyID: "text", - }, - { - label: "Text Color", - type: "color", - propertyID: "textColor", - }, - { - label: "Text Alpha", - type: "number-draggable", - min: 0, - max: 1, - step: 0.01, - decimals: 2, - propertyID: "textAlpha", - }, - { - label: "Background Color", - type: "color", - propertyID: "backgroundColor", - }, - { - label: "Background Alpha", - type: "number-draggable", - min: 0, - max: 1, - step: 0.01, - decimals: 2, - propertyID: "backgroundAlpha", - }, - { - label: "Line Height", - type: "number-draggable", - min: 0, - step: 0.001, - decimals: 4, - unit: "m", - propertyID: "lineHeight", - }, - { - label: "Billboard Mode", - type: "dropdown", - options: { none: "None", yaw: "Yaw", full: "Full"}, - propertyID: "textBillboardMode", - propertyName: "billboardMode", // actual entity property name - }, - { - label: "Top Margin", - type: "number-draggable", - step: 0.01, - decimals: 2, - propertyID: "topMargin", - }, - { - label: "Right Margin", - type: "number-draggable", - step: 0.01, - decimals: 2, - propertyID: "rightMargin", - }, - { - label: "Bottom Margin", - type: "number-draggable", - step: 0.01, - decimals: 2, - propertyID: "bottomMargin", - }, - { - label: "Left Margin", - type: "number-draggable", - step: 0.01, - decimals: 2, - propertyID: "leftMargin", - }, - ] - }, - { - id: "zone", - addToGroup: "base", - properties: [ - { - label: "Shape Type", - type: "dropdown", - options: { "box": "Box", "sphere": "Sphere", "ellipsoid": "Ellipsoid", - "cylinder-y": "Cylinder", "compound": "Use Compound Shape URL" }, - propertyID: "zoneShapeType", - propertyName: "shapeType", // actual entity property name - }, - { - label: "Compound Shape URL", - type: "string", - propertyID: "zoneCompoundShapeURL", - propertyName: "compoundShapeURL", // actual entity property name - }, - { - label: "Flying Allowed", - type: "bool", - propertyID: "flyingAllowed", - }, - { - label: "Ghosting Allowed", - type: "bool", - propertyID: "ghostingAllowed", - }, - { - label: "Filter", - type: "string", - propertyID: "filterURL", - }, - { - label: "Key Light", - type: "dropdown", - options: { inherit: "Inherit", disabled: "Off", enabled: "On" }, - propertyID: "keyLightMode", - - }, - { - label: "Key Light Color", - type: "color", - propertyID: "keyLight.color", - showPropertyRule: { "keyLightMode": "enabled" }, - }, - { - label: "Light Intensity", - type: "number-draggable", - min: 0, - max: 40, - step: 0.01, - decimals: 2, - propertyID: "keyLight.intensity", - showPropertyRule: { "keyLightMode": "enabled" }, - }, - { - label: "Light Horizontal Angle", - type: "number-draggable", - step: 0.1, - multiplier: DEGREES_TO_RADIANS, - decimals: 2, - unit: "deg", - propertyID: "keyLight.direction.y", - showPropertyRule: { "keyLightMode": "enabled" }, - }, - { - label: "Light Vertical Angle", - type: "number-draggable", - step: 0.1, - multiplier: DEGREES_TO_RADIANS, - decimals: 2, - unit: "deg", - propertyID: "keyLight.direction.x", - showPropertyRule: { "keyLightMode": "enabled" }, - }, - { - label: "Cast Shadows", - type: "bool", - propertyID: "keyLight.castShadows", - showPropertyRule: { "keyLightMode": "enabled" }, - }, - { - label: "Skybox", - type: "dropdown", - options: { inherit: "Inherit", disabled: "Off", enabled: "On" }, - propertyID: "skyboxMode", - }, - { - label: "Skybox Color", - type: "color", - propertyID: "skybox.color", - showPropertyRule: { "skyboxMode": "enabled" }, - }, - { - label: "Skybox Source", - type: "string", - propertyID: "skybox.url", - showPropertyRule: { "skyboxMode": "enabled" }, - }, - { - label: "Ambient Light", - type: "dropdown", - options: { inherit: "Inherit", disabled: "Off", enabled: "On" }, - propertyID: "ambientLightMode", - }, - { - label: "Ambient Intensity", - type: "number-draggable", - min: 0, - max: 200, - step: 0.1, - decimals: 2, - propertyID: "ambientLight.ambientIntensity", - showPropertyRule: { "ambientLightMode": "enabled" }, - }, - { - label: "Ambient Source", - type: "string", - propertyID: "ambientLight.ambientURL", - showPropertyRule: { "ambientLightMode": "enabled" }, - }, - { - type: "buttons", - buttons: [ { id: "copy", label: "Copy from Skybox", - className: "black", onClick: copySkyboxURLToAmbientURL } ], - propertyID: "copyURLToAmbient", - showPropertyRule: { "ambientLightMode": "enabled" }, - }, - { - label: "Haze", - type: "dropdown", - options: { inherit: "Inherit", disabled: "Off", enabled: "On" }, - propertyID: "hazeMode", - }, - { - label: "Range", - type: "number-draggable", - min: 1, - max: 10000, - step: 1, - decimals: 0, - unit: "m", - propertyID: "haze.hazeRange", - showPropertyRule: { "hazeMode": "enabled" }, - }, - { - label: "Use Altitude", - type: "bool", - propertyID: "haze.hazeAltitudeEffect", - showPropertyRule: { "hazeMode": "enabled" }, - }, - { - label: "Base", - type: "number-draggable", - min: -1000, - max: 1000, - step: 1, - decimals: 0, - unit: "m", - propertyID: "haze.hazeBaseRef", - showPropertyRule: { "hazeMode": "enabled" }, - }, - { - label: "Ceiling", - type: "number-draggable", - min: -1000, - max: 5000, - step: 1, - decimals: 0, - unit: "m", - propertyID: "haze.hazeCeiling", - showPropertyRule: { "hazeMode": "enabled" }, - }, - { - label: "Haze Color", - type: "color", - propertyID: "haze.hazeColor", - showPropertyRule: { "hazeMode": "enabled" }, - }, - { - label: "Background Blend", - type: "number-draggable", - min: 0, - max: 1, - step: 0.001, - decimals: 3, - propertyID: "haze.hazeBackgroundBlend", - showPropertyRule: { "hazeMode": "enabled" }, - }, - { - label: "Enable Glare", - type: "bool", - propertyID: "haze.hazeEnableGlare", - showPropertyRule: { "hazeMode": "enabled" }, - }, - { - label: "Glare Color", - type: "color", - propertyID: "haze.hazeGlareColor", - showPropertyRule: { "hazeMode": "enabled" }, - }, - { - label: "Glare Angle", - type: "number-draggable", - min: 0, - max: 180, - step: 1, - decimals: 0, - propertyID: "haze.hazeGlareAngle", - showPropertyRule: { "hazeMode": "enabled" }, - }, - { - label: "Bloom", - type: "dropdown", - options: { inherit: "Inherit", disabled: "Off", enabled: "On" }, - propertyID: "bloomMode", - }, - { - label: "Bloom Intensity", - type: "number-draggable", - min: 0, - max: 1, - step: 0.001, - decimals: 3, - propertyID: "bloom.bloomIntensity", - showPropertyRule: { "bloomMode": "enabled" }, - }, - { - label: "Bloom Threshold", - type: "number-draggable", - min: 0, - max: 1, - step: 0.001, - decimals: 3, - propertyID: "bloom.bloomThreshold", - showPropertyRule: { "bloomMode": "enabled" }, - }, - { - label: "Bloom Size", - type: "number-draggable", - min: 0, - max: 2, - step: 0.001, - decimals: 3, - propertyID: "bloom.bloomSize", - showPropertyRule: { "bloomMode": "enabled" }, - }, - { - label: "Avatar Priority", - type: "dropdown", - options: { inherit: "Inherit", crowd: "Crowd", hero: "Hero" }, - propertyID: "avatarPriority", - }, - - ] - }, - { - id: "model", - addToGroup: "base", - properties: [ - { - label: "Model", - type: "string", - placeholder: "URL", - propertyID: "modelURL", - hideIfCertified: true, - }, - { - label: "Collision Shape", - type: "dropdown", - options: { "none": "No Collision", "box": "Box", "sphere": "Sphere", "compound": "Compound" , - "simple-hull": "Basic - Whole model", "simple-compound": "Good - Sub-meshes" , - "static-mesh": "Exact - All polygons (non-dynamic only)" }, - propertyID: "shapeType", - }, - { - label: "Compound Shape", - type: "string", - propertyID: "compoundShapeURL", - hideIfCertified: true, - }, - { - label: "Animation", - type: "string", - propertyID: "animation.url", - hideIfCertified: true, - }, - { - label: "Play Automatically", - type: "bool", - propertyID: "animation.running", - }, - { - label: "Loop", - type: "bool", - propertyID: "animation.loop", - }, - { - label: "Allow Transition", - type: "bool", - propertyID: "animation.allowTranslation", - }, - { - label: "Hold", - type: "bool", - propertyID: "animation.hold", - }, - { - label: "Animation Frame", - type: "number-draggable", - propertyID: "animation.currentFrame", - }, - { - label: "First Frame", - type: "number-draggable", - propertyID: "animation.firstFrame", - }, - { - label: "Last Frame", - type: "number-draggable", - propertyID: "animation.lastFrame", - }, - { - label: "Animation FPS", - type: "number-draggable", - propertyID: "animation.fps", - }, - { - label: "Texture", - type: "textarea", - propertyID: "textures", - }, - { - label: "Original Texture", - type: "textarea", - propertyID: "originalTextures", - readOnly: true, - hideIfCertified: true, - }, - { - label: "Group Culled", - type: "bool", - propertyID: "groupCulled", - }, - ] - }, - { - id: "image", - addToGroup: "base", - properties: [ - { - label: "Image", - type: "string", - placeholder: "URL", - propertyID: "imageURL", - }, - { - label: "Color", - type: "color", - propertyID: "imageColor", - propertyName: "color", // actual entity property name - }, - { - label: "Emissive", - type: "bool", - propertyID: "emissive", - }, - { - label: "Sub Image", - type: "rect", - min: 0, - step: 1, - subLabels: [ "x", "y", "w", "h" ], - propertyID: "subImage", - }, - { - label: "Billboard Mode", - type: "dropdown", - options: { none: "None", yaw: "Yaw", full: "Full"}, - propertyID: "imageBillboardMode", - propertyName: "billboardMode", // actual entity property name - }, - { - label: "Keep Aspect Ratio", - type: "bool", - propertyID: "keepAspectRatio", - }, - ] - }, - { - id: "web", - addToGroup: "base", - properties: [ - { - label: "Source", - type: "string", - propertyID: "sourceUrl", - }, - { - label: "Source Resolution", - type: "number-draggable", - propertyID: "dpi", - }, - { - label: "Web Color", - type: "color", - propertyID: "webColor", - propertyName: "color", // actual entity property name - }, - { - label: "Web Alpha", - type: "number-draggable", - step: 0.001, - decimals: 3, - propertyID: "webAlpha", - propertyName: "alpha", - min: 0, - max: 1, - }, - { - label: "Max FPS", - type: "number-draggable", - step: 1, - decimals: 0, - propertyID: "maxFPS", - }, - { - label: "Script URL", - type: "string", - propertyID: "scriptURL", - placeholder: "URL", - }, - ] - }, - { - id: "light", - addToGroup: "base", - properties: [ - { - label: "Light Color", - type: "color", - propertyID: "lightColor", - propertyName: "color", // actual entity property name - }, - { - label: "Intensity", - type: "number-draggable", - min: 0, - max: 10000, - step: 0.1, - decimals: 2, - propertyID: "intensity", - }, - { - label: "Fall-Off Radius", - type: "number-draggable", - min: 0, - max: 10000, - step: 0.1, - decimals: 2, - unit: "m", - propertyID: "falloffRadius", - }, - { - label: "Spotlight", - type: "bool", - propertyID: "isSpotlight", - }, - { - label: "Spotlight Exponent", - type: "number-draggable", - min: 0, - step: 0.01, - decimals: 2, - propertyID: "exponent", - }, - { - label: "Spotlight Cut-Off", - type: "number-draggable", - step: 0.01, - decimals: 2, - propertyID: "cutoff", - }, - ] - }, - { - id: "material", - addToGroup: "base", - properties: [ - { - label: "Material URL", - type: "string", - propertyID: "materialURL", - }, - { - label: "Material Data", - type: "textarea", - buttons: [ { id: "clear", label: "Clear Material Data", className: "red", onClick: clearMaterialData }, - { id: "edit", label: "Edit as JSON", className: "blue", onClick: newJSONMaterialEditor }, - { id: "save", label: "Save Material Data", className: "black", onClick: saveMaterialData } ], - propertyID: "materialData", - }, - { - label: "Material Target", - type: "dynamic-multiselect", - propertyUpdate: materialTargetPropertyUpdate, - propertyID: "parentMaterialName", - selectionVisibility: PROPERTY_SELECTION_VISIBILITY.SINGLE_SELECTION, - }, - { - label: "Priority", - type: "number-draggable", - min: 0, - propertyID: "priority", - }, - { - label: "Material Mapping Mode", - type: "dropdown", - options: { - uv: "UV space", projected: "3D projected" - }, - propertyID: "materialMappingMode", - }, - { - label: "Material Position", - type: "vec2", - vec2Type: "xyz", - min: 0, - max: 1, - step: 0.1, - decimals: 4, - subLabels: [ "x", "y" ], - propertyID: "materialMappingPos", - }, - { - label: "Material Scale", - type: "vec2", - vec2Type: "xyz", - min: 0, - step: 0.1, - decimals: 4, - subLabels: [ "x", "y" ], - propertyID: "materialMappingScale", - }, - { - label: "Material Rotation", - type: "number-draggable", - step: 0.1, - decimals: 2, - unit: "deg", - propertyID: "materialMappingRot", - }, - { - label: "Material Repeat", - type: "bool", - propertyID: "materialRepeat", - }, - ] - }, - { - id: "grid", - addToGroup: "base", - properties: [ - { - label: "Color", - type: "color", - propertyID: "gridColor", - propertyName: "color", // actual entity property name - }, - { - label: "Follow Camera", - type: "bool", - propertyID: "followCamera", - }, - { - label: "Major Grid Every", - type: "number-draggable", - min: 0, - step: 1, - decimals: 0, - propertyID: "majorGridEvery", - }, - { - label: "Minor Grid Every", - type: "number-draggable", - min: 0, - step: 0.01, - decimals: 2, - propertyID: "minorGridEvery", - }, - ] - }, - { - id: "particles", - addToGroup: "base", - properties: [ - { - label: "Emit", - type: "bool", - propertyID: "isEmitting", - }, - { - label: "Lifespan", - type: "number-draggable", - unit: "s", - step: 0.01, - decimals: 2, - propertyID: "lifespan", - }, - { - label: "Max Particles", - type: "number-draggable", - step: 1, - propertyID: "maxParticles", - }, - { - label: "Texture", - type: "texture", - propertyID: "particleTextures", - propertyName: "textures", // actual entity property name - }, - ] - }, - { - id: "particles_emit", - label: "EMIT", - isMinor: true, - properties: [ - { - label: "Emit Rate", - type: "number-draggable", - step: 1, - propertyID: "emitRate", - }, - { - label: "Emit Speed", - type: "number-draggable", - step: 0.1, - decimals: 2, - propertyID: "emitSpeed", - }, - { - label: "Speed Spread", - type: "number-draggable", - step: 0.1, - decimals: 2, - propertyID: "speedSpread", - }, - { - label: "Shape Type", - type: "dropdown", - options: { "box": "Box", "ellipsoid": "Ellipsoid", - "cylinder-y": "Cylinder", "circle": "Circle", "plane": "Plane", - "compound": "Use Compound Shape URL" }, - propertyID: "particleShapeType", - propertyName: "shapeType", - }, - { - label: "Compound Shape URL", - type: "string", - propertyID: "particleCompoundShapeURL", - propertyName: "compoundShapeURL", - }, - { - label: "Emit Dimensions", - type: "vec3", - vec3Type: "xyz", - step: 0.01, - round: 100, - subLabels: [ "x", "y", "z" ], - propertyID: "emitDimensions", - }, - { - label: "Emit Radius Start", - type: "number-draggable", - step: 0.001, - decimals: 3, - propertyID: "emitRadiusStart" - }, - { - label: "Emit Orientation", - type: "vec3", - vec3Type: "pyr", - step: 0.01, - round: 100, - subLabels: [ "x", "y", "z" ], - unit: "deg", - propertyID: "emitOrientation", - }, - { - label: "Trails", - type: "bool", - propertyID: "emitterShouldTrail", - }, - ] - }, - { - id: "particles_size", - label: "SIZE", - isMinor: true, - properties: [ - { - type: "triple", - label: "Size", - propertyID: "particleRadiusTriple", - properties: [ - { - label: "Start", - type: "number-draggable", - step: 0.01, - decimals: 2, - propertyID: "radiusStart", - fallbackProperty: "particleRadius", - }, - { - label: "Middle", - type: "number-draggable", - step: 0.01, - decimals: 2, - propertyID: "particleRadius", - }, - { - label: "Finish", - type: "number-draggable", - step: 0.01, - decimals: 2, - propertyID: "radiusFinish", - fallbackProperty: "particleRadius", - }, - ] - }, - { - label: "Size Spread", - type: "number-draggable", - step: 0.01, - decimals: 2, - propertyID: "radiusSpread", - }, - ] - }, - { - id: "particles_color", - label: "COLOR", - isMinor: true, - properties: [ - { - type: "triple", - label: "Color", - propertyID: "particleColorTriple", - properties: [ - { - label: "Start", - type: "color", - propertyID: "colorStart", - fallbackProperty: "color", - }, - { - label: "Middle", - type: "color", - propertyID: "particleColor", - propertyName: "color", // actual entity property name - }, - { - label: "Finish", - type: "color", - propertyID: "colorFinish", - fallbackProperty: "color", - }, - ] - }, - { - label: "Color Spread", - type: "color", - propertyID: "colorSpread", - }, - ] - }, - { - id: "particles_alpha", - label: "ALPHA", - isMinor: true, - properties: [ - { - type: "triple", - label: "Alpha", - propertyID: "particleAlphaTriple", - properties: [ - { - label: "Start", - type: "number-draggable", - step: 0.001, - decimals: 3, - propertyID: "alphaStart", - fallbackProperty: "alpha", - }, - { - label: "Middle", - type: "number-draggable", - step: 0.001, - decimals: 3, - propertyID: "alpha", - }, - { - label: "Finish", - type: "number-draggable", - step: 0.001, - decimals: 3, - propertyID: "alphaFinish", - fallbackProperty: "alpha", - }, - ] - }, - { - label: "Alpha Spread", - type: "number-draggable", - step: 0.001, - decimals: 3, - propertyID: "alphaSpread", - }, - ] - }, - { - id: "particles_acceleration", - label: "ACCELERATION", - isMinor: true, - properties: [ - { - label: "Emit Acceleration", - type: "vec3", - vec3Type: "xyz", - step: 0.01, - round: 100, - subLabels: [ "x", "y", "z" ], - propertyID: "emitAcceleration", - }, - { - label: "Acceleration Spread", - type: "vec3", - vec3Type: "xyz", - step: 0.01, - round: 100, - subLabels: [ "x", "y", "z" ], - propertyID: "accelerationSpread", - }, - ] - }, - { - id: "particles_spin", - label: "SPIN", - isMinor: true, - properties: [ - { - type: "triple", - label: "Spin", - propertyID: "particleSpinTriple", - properties: [ - { - label: "Start", - type: "number-draggable", - step: 0.1, - decimals: 2, - multiplier: DEGREES_TO_RADIANS, - unit: "deg", - propertyID: "spinStart", - fallbackProperty: "particleSpin", - }, - { - label: "Middle", - type: "number-draggable", - step: 0.1, - decimals: 2, - multiplier: DEGREES_TO_RADIANS, - unit: "deg", - propertyID: "particleSpin", - }, - { - label: "Finish", - type: "number-draggable", - step: 0.1, - decimals: 2, - multiplier: DEGREES_TO_RADIANS, - unit: "deg", - propertyID: "spinFinish", - fallbackProperty: "particleSpin", - }, - ] - }, - { - label: "Spin Spread", - type: "number-draggable", - step: 0.1, - decimals: 2, - multiplier: DEGREES_TO_RADIANS, - unit: "deg", - propertyID: "spinSpread", - }, - { - label: "Rotate with Entity", - type: "bool", - propertyID: "rotateWithEntity", - }, - ] - }, - { - id: "particles_constraints", - label: "CONSTRAINTS", - isMinor: true, - properties: [ - { - type: "triple", - label: "Horizontal Angle", - propertyID: "particlePolarTriple", - properties: [ - { - label: "Start", - type: "number-draggable", - step: 0.1, - decimals: 2, - multiplier: DEGREES_TO_RADIANS, - unit: "deg", - propertyID: "polarStart", - }, - { - label: "Finish", - type: "number-draggable", - step: 0.1, - decimals: 2, - multiplier: DEGREES_TO_RADIANS, - unit: "deg", - propertyID: "polarFinish", - }, - ], - }, - { - type: "triple", - label: "Vertical Angle", - propertyID: "particleAzimuthTriple", - properties: [ - { - label: "Start", - type: "number-draggable", - step: 0.1, - decimals: 2, - multiplier: DEGREES_TO_RADIANS, - unit: "deg", - propertyID: "azimuthStart", - }, - { - label: "Finish", - type: "number-draggable", - step: 0.1, - decimals: 2, - multiplier: DEGREES_TO_RADIANS, - unit: "deg", - propertyID: "azimuthFinish", - }, - ] - } - ] - }, - { - id: "spatial", - label: "SPATIAL", - properties: [ - { - label: "Position", - type: "vec3", - vec3Type: "xyz", - step: 0.1, - decimals: 4, - subLabels: [ "x", "y", "z" ], - unit: "m", - propertyID: "position", - spaceMode: PROPERTY_SPACE_MODE.WORLD, - }, - { - label: "Local Position", - type: "vec3", - vec3Type: "xyz", - step: 0.1, - decimals: 4, - subLabels: [ "x", "y", "z" ], - unit: "m", - propertyID: "localPosition", - spaceMode: PROPERTY_SPACE_MODE.LOCAL, - }, - { - label: "Rotation", - type: "vec3", - vec3Type: "pyr", - step: 0.1, - decimals: 4, - subLabels: [ "x", "y", "z" ], - unit: "deg", - propertyID: "rotation", - spaceMode: PROPERTY_SPACE_MODE.WORLD, - }, - { - label: "Local Rotation", - type: "vec3", - vec3Type: "pyr", - step: 0.1, - decimals: 4, - subLabels: [ "x", "y", "z" ], - unit: "deg", - propertyID: "localRotation", - spaceMode: PROPERTY_SPACE_MODE.LOCAL, - }, - { - label: "Dimensions", - type: "vec3", - vec3Type: "xyz", - step: 0.01, - decimals: 4, - subLabels: [ "x", "y", "z" ], - unit: "m", - propertyID: "dimensions", - spaceMode: PROPERTY_SPACE_MODE.WORLD, - }, - { - label: "Local Dimensions", - type: "vec3", - vec3Type: "xyz", - step: 0.01, - decimals: 4, - subLabels: [ "x", "y", "z" ], - unit: "m", - propertyID: "localDimensions", - spaceMode: PROPERTY_SPACE_MODE.LOCAL, - }, - { - label: "Scale", - type: "number-draggable", - defaultValue: 100, - unit: "%", - buttons: [ { id: "rescale", label: "Rescale", className: "blue", onClick: rescaleDimensions }, - { id: "reset", label: "Reset Dimensions", className: "red", onClick: resetToNaturalDimensions } ], - propertyID: "scale", - }, - { - label: "Pivot", - type: "vec3", - vec3Type: "xyz", - step: 0.001, - decimals: 4, - subLabels: [ "x", "y", "z" ], - unit: "(ratio of dimension)", - propertyID: "registrationPoint", - }, - { - label: "Align", - type: "buttons", - buttons: [ { id: "selection", label: "Selection to Grid", className: "black", onClick: moveSelectionToGrid }, - { id: "all", label: "All to Grid", className: "black", onClick: moveAllToGrid } ], - propertyID: "alignToGrid", - }, - ] - }, - { - id: "behavior", - label: "BEHAVIOR", - properties: [ - { - label: "Grabbable", - type: "bool", - propertyID: "grab.grabbable", - }, - { - label: "Cloneable", - type: "bool", - propertyID: "cloneable", - }, - { - label: "Clone Lifetime", - type: "number-draggable", - min: -1, - unit: "s", - propertyID: "cloneLifetime", - showPropertyRule: { "cloneable": "true" }, - }, - { - label: "Clone Limit", - type: "number-draggable", - min: 0, - propertyID: "cloneLimit", - showPropertyRule: { "cloneable": "true" }, - }, - { - label: "Clone Dynamic", - type: "bool", - propertyID: "cloneDynamic", - showPropertyRule: { "cloneable": "true" }, - }, - { - label: "Clone Avatar Entity", - type: "bool", - propertyID: "cloneAvatarEntity", - showPropertyRule: { "cloneable": "true" }, - }, - { - label: "Triggerable", - type: "bool", - propertyID: "grab.triggerable", - }, - { - label: "Follow Controller", - type: "bool", - propertyID: "grab.grabFollowsController", - }, - { - label: "Cast Shadows", - type: "bool", - propertyID: "canCastShadow", - }, - { - label: "Link", - type: "string", - propertyID: "href", - placeholder: "URL", - }, - { - label: "Ignore Pick Intersection", - type: "bool", - propertyID: "ignorePickIntersection", - }, - { - label: "Script", - type: "string", - buttons: [ { id: "reload", label: "F", className: "glyph", onClick: reloadScripts } ], - propertyID: "script", - placeholder: "URL", - hideIfCertified: true, - }, - { - label: "Server Script", - type: "string", - buttons: [ { id: "reload", label: "F", className: "glyph", onClick: reloadServerScripts } ], - propertyID: "serverScripts", - placeholder: "URL", - }, - { - label: "Server Script Status", - type: "placeholder", - indentedLabel: true, - propertyID: "serverScriptStatus", - selectionVisibility: PROPERTY_SELECTION_VISIBILITY.SINGLE_SELECTION, - }, - { - label: "Lifetime", - type: "number", - unit: "s", - propertyID: "lifetime", - }, - { - label: "User Data", - type: "textarea", - buttons: [ { id: "clear", label: "Clear User Data", className: "red", onClick: clearUserData }, - { id: "edit", label: "Edit as JSON", className: "blue", onClick: newJSONEditor }, - { id: "save", label: "Save User Data", className: "black", onClick: saveUserData } ], - propertyID: "userData", - }, - ] - }, - { - id: "collision", - label: "COLLISION", - properties: [ - { - label: "Collides", - type: "bool", - inverse: true, - propertyID: "collisionless", - }, - { - label: "Static Entities", - type: "bool", - propertyID: "collidesWithStatic", - propertyName: "static", // actual subProperty name - subPropertyOf: "collidesWith", - showPropertyRule: { "collisionless": "false" }, - }, - { - label: "Kinematic Entities", - type: "bool", - propertyID: "collidesWithKinematic", - propertyName: "kinematic", // actual subProperty name - subPropertyOf: "collidesWith", - showPropertyRule: { "collisionless": "false" }, - }, - { - label: "Dynamic Entities", - type: "bool", - propertyID: "collidesWithDynamic", - propertyName: "dynamic", // actual subProperty name - subPropertyOf: "collidesWith", - showPropertyRule: { "collisionless": "false" }, - }, - { - label: "My Avatar", - type: "bool", - propertyID: "collidesWithMyAvatar", - propertyName: "myAvatar", // actual subProperty name - subPropertyOf: "collidesWith", - showPropertyRule: { "collisionless": "false" }, - }, - { - label: "Other Avatars", - type: "bool", - propertyID: "collidesWithOtherAvatar", - propertyName: "otherAvatar", // actual subProperty name - subPropertyOf: "collidesWith", - showPropertyRule: { "collisionless": "false" }, - }, - { - label: "Collision Sound", - type: "string", - placeholder: "URL", - propertyID: "collisionSoundURL", - showPropertyRule: { "collisionless": "false" }, - hideIfCertified: true, - }, - { - label: "Dynamic", - type: "bool", - propertyID: "dynamic", - }, - ] - }, - { - id: "physics", - label: "PHYSICS", - properties: [ - { - label: "Linear Velocity", - type: "vec3", - vec3Type: "xyz", - step: 0.01, - decimals: 4, - subLabels: [ "x", "y", "z" ], - unit: "m/s", - propertyID: "localVelocity", - }, - { - label: "Linear Damping", - type: "number-draggable", - min: 0, - max: 1, - step: 0.001, - decimals: 4, - propertyID: "damping", - }, - { - label: "Angular Velocity", - type: "vec3", - vec3Type: "pyr", - multiplier: DEGREES_TO_RADIANS, - decimals: 4, - subLabels: [ "x", "y", "z" ], - unit: "deg/s", - propertyID: "localAngularVelocity", - }, - { - label: "Angular Damping", - type: "number-draggable", - min: 0, - max: 1, - step: 0.001, - decimals: 4, - propertyID: "angularDamping", - }, - { - label: "Bounciness", - type: "number-draggable", - step: 0.001, - decimals: 4, - propertyID: "restitution", - }, - { - label: "Friction", - type: "number-draggable", - step: 0.01, - decimals: 4, - propertyID: "friction", - }, - { - label: "Density", - type: "number-draggable", - step: 1, - decimals: 4, - propertyID: "density", - }, - { - label: "Gravity", - type: "vec3", - vec3Type: "xyz", - subLabels: [ "x", "y", "z" ], - step: 0.1, - decimals: 4, - unit: "m/s2", - propertyID: "gravity", - }, - { - label: "Acceleration", - type: "vec3", - vec3Type: "xyz", - subLabels: [ "x", "y", "z" ], - step: 0.1, - decimals: 4, - unit: "m/s2", - propertyID: "acceleration", - }, - ] - }, -]; - -const GROUPS_PER_TYPE = { - None: [ 'base', 'spatial', 'behavior', 'collision', 'physics' ], - Shape: [ 'base', 'shape', 'spatial', 'behavior', 'collision', 'physics' ], - Text: [ 'base', 'text', 'spatial', 'behavior', 'collision', 'physics' ], - Zone: [ 'base', 'zone', 'spatial', 'behavior', 'physics' ], - Model: [ 'base', 'model', 'spatial', 'behavior', 'collision', 'physics' ], - Image: [ 'base', 'image', 'spatial', 'behavior', 'collision', 'physics' ], - Web: [ 'base', 'web', 'spatial', 'behavior', 'collision', 'physics' ], - Light: [ 'base', 'light', 'spatial', 'behavior', 'collision', 'physics' ], - Material: [ 'base', 'material', 'spatial', 'behavior' ], - ParticleEffect: [ 'base', 'particles', 'particles_emit', 'particles_size', 'particles_color', 'particles_alpha', - 'particles_acceleration', 'particles_spin', 'particles_constraints', 'spatial', 'behavior', 'physics' ], - PolyLine: [ 'base', 'spatial', 'behavior', 'collision', 'physics' ], - PolyVox: [ 'base', 'spatial', 'behavior', 'collision', 'physics' ], - Grid: [ 'base', 'grid', 'spatial', 'behavior', 'physics' ], - Multiple: [ 'base', 'spatial', 'behavior', 'collision', 'physics' ], -}; - -const EDITOR_TIMEOUT_DURATION = 1500; -const DEBOUNCE_TIMEOUT = 125; - -const COLOR_MIN = 0; -const COLOR_MAX = 255; -const COLOR_STEP = 1; - -const MATERIAL_PREFIX_STRING = "mat::"; - -const PENDING_SCRIPT_STATUS = "[ Fetching status ]"; -const NOT_RUNNING_SCRIPT_STATUS = "Not running"; -const ENTITY_SCRIPT_STATUS = { - pending: "Pending", - loading: "Loading", - error_loading_script: "Error loading script", // eslint-disable-line camelcase - error_running_script: "Error running script", // eslint-disable-line camelcase - running: "Running", - unloaded: "Unloaded" -}; - -const ENABLE_DISABLE_SELECTOR = "input, textarea, span, .dropdown dl, .color-picker"; - -const PROPERTY_NAME_DIVISION = { - GROUP: 0, - PROPERTY: 1, - SUB_PROPERTY: 2, -}; - -const RECT_ELEMENTS = { - X_NUMBER: 0, - Y_NUMBER: 1, - WIDTH_NUMBER: 2, - HEIGHT_NUMBER: 3, -}; - -const VECTOR_ELEMENTS = { - X_NUMBER: 0, - Y_NUMBER: 1, - Z_NUMBER: 2, -}; - -const COLOR_ELEMENTS = { - COLOR_PICKER: 0, - RED_NUMBER: 1, - GREEN_NUMBER: 2, - BLUE_NUMBER: 3, -}; - -const TEXTURE_ELEMENTS = { - IMAGE: 0, - TEXT_INPUT: 1, -}; - -const JSON_EDITOR_ROW_DIV_INDEX = 2; - -let elGroups = {}; -let properties = {}; -let propertyRangeRequests = []; -let colorPickers = {}; -let particlePropertyUpdates = {}; -let selectedEntityIDs = new Set(); -let currentSelections = []; -let createAppTooltip = new CreateAppTooltip(); -let currentSpaceMode = PROPERTY_SPACE_MODE.LOCAL; - - -function createElementFromHTML(htmlString) { - let elTemplate = document.createElement('template'); - elTemplate.innerHTML = htmlString.trim(); - return elTemplate.content.firstChild; -} - -function isFlagSet(value, flag) { - return (value & flag) === flag; -} - -/** - * GENERAL PROPERTY/GROUP FUNCTIONS - */ - -function getPropertyInputElement(propertyID) { - let property = properties[propertyID]; - switch (property.data.type) { - case 'string': - case 'number': - case 'bool': - case 'dropdown': - case 'textarea': - case 'texture': - return property.elInput; - case 'number-draggable': - return property.elNumber.elInput; - case 'rect': - return { - x: property.elNumberX.elInput, - y: property.elNumberY.elInput, - width: property.elNumberWidth.elInput, - height: property.elNumberHeight.elInput - }; - case 'vec3': - case 'vec2': - return { x: property.elNumberX.elInput, y: property.elNumberY.elInput, z: property.elNumberZ.elInput }; - case 'color': - return { red: property.elNumberR.elInput, green: property.elNumberG.elInput, blue: property.elNumberB.elInput }; - case 'icon': - return property.elLabel; - case 'dynamic-multiselect': - return property.elDivOptions; - default: - return undefined; - } -} - -function enableChildren(el, selector) { - let elSelectors = el.querySelectorAll(selector); - for (let selectorIndex = 0; selectorIndex < elSelectors.length; ++selectorIndex) { - elSelectors[selectorIndex].removeAttribute('disabled'); - } -} - -function disableChildren(el, selector) { - let elSelectors = el.querySelectorAll(selector); - for (let selectorIndex = 0; selectorIndex < elSelectors.length; ++selectorIndex) { - elSelectors[selectorIndex].setAttribute('disabled', 'disabled'); - } -} - -function enableProperties() { - enableChildren(document.getElementById("properties-list"), ENABLE_DISABLE_SELECTOR); - enableChildren(document, ".colpick"); - - let elLocked = getPropertyInputElement("locked"); - if (elLocked.checked === false) { - removeStaticUserData(); - removeStaticMaterialData(); - } -} - -function disableProperties() { - disableChildren(document.getElementById("properties-list"), ENABLE_DISABLE_SELECTOR); - disableChildren(document, ".colpick"); - for (let pickKey in colorPickers) { - colorPickers[pickKey].colpickHide(); - } - - let elLocked = getPropertyInputElement("locked"); - if (elLocked.checked === true) { - if ($('#property-userData-editor').css('display') === "block") { - showStaticUserData(); - } - if ($('#property-materialData-editor').css('display') === "block") { - showStaticMaterialData(); - } - } -} - -function showPropertyElement(propertyID, show) { - setPropertyVisibility(properties[propertyID], show); -} - -function setPropertyVisibility(property, visible) { - property.elContainer.style.display = visible ? null : "none"; -} - -function resetProperties() { - for (let propertyID in properties) { - let property = properties[propertyID]; - let propertyData = property.data; - - switch (propertyData.type) { - case 'number': - case 'string': { - property.elInput.classList.remove('multi-diff'); - if (propertyData.defaultValue !== undefined) { - property.elInput.value = propertyData.defaultValue; - } else { - property.elInput.value = ""; - } - break; - } - case 'bool': { - property.elInput.classList.remove('multi-diff'); - property.elInput.checked = false; - break; - } - case 'number-draggable': { - if (propertyData.defaultValue !== undefined) { - property.elNumber.setValue(propertyData.defaultValue, false); - } else { - property.elNumber.setValue("", false); - } - break; - } - case 'rect': { - property.elNumberX.setValue("", false); - property.elNumberY.setValue("", false); - property.elNumberWidth.setValue("", false); - property.elNumberHeight.setValue("", false); - break; - } - case 'vec3': - case 'vec2': { - property.elNumberX.setValue("", false); - property.elNumberY.setValue("", false); - if (property.elNumberZ !== undefined) { - property.elNumberZ.setValue("", false); - } - break; - } - case 'color': { - property.elColorPicker.style.backgroundColor = "rgb(" + 0 + "," + 0 + "," + 0 + ")"; - property.elNumberR.setValue("", false); - property.elNumberG.setValue("", false); - property.elNumberB.setValue("", false); - break; - } - case 'dropdown': { - property.elInput.classList.remove('multi-diff'); - property.elInput.value = ""; - setDropdownText(property.elInput); - break; - } - case 'textarea': { - property.elInput.classList.remove('multi-diff'); - property.elInput.value = ""; - setTextareaScrolling(property.elInput); - break; - } - case 'icon': { - property.elSpan.style.display = "none"; - break; - } - case 'texture': { - property.elInput.classList.remove('multi-diff'); - property.elInput.value = ""; - property.elInput.imageLoad(property.elInput.value); - break; - } - case 'dynamic-multiselect': { - resetDynamicMultiselectProperty(property.elDivOptions); - break; - } - } - - let showPropertyRules = properties[propertyID].showPropertyRules; - if (showPropertyRules !== undefined) { - for (let propertyToHide in showPropertyRules) { - showPropertyElement(propertyToHide, false); - } - } - } - - resetServerScriptStatus(); -} - -function resetServerScriptStatus() { - let elServerScriptError = document.getElementById("property-serverScripts-error"); - let elServerScriptStatus = document.getElementById("property-serverScripts-status"); - elServerScriptError.parentElement.style.display = "none"; - elServerScriptStatus.innerText = NOT_RUNNING_SCRIPT_STATUS; -} - -function showGroupsForType(type) { - if (type === "Box" || type === "Sphere") { - showGroupsForTypes(["Shape"]); - return; - } - showGroupsForTypes([type]); -} - -function getGroupsForTypes(types) { - return Object.keys(elGroups).filter((groupKey) => { - return types.map(type => GROUPS_PER_TYPE[type].includes(groupKey)).every(function (hasGroup) { - return hasGroup; - }); - }); -} - -function showGroupsForTypes(types) { - Object.entries(elGroups).forEach(([groupKey, elGroup]) => { - if (types.map(type => GROUPS_PER_TYPE[type].includes(groupKey)).every(function (hasGroup) { return hasGroup; })) { - elGroup.style.display = "block"; - } else { - elGroup.style.display = "none"; - } - }); -} - -function getFirstSelectedID() { - if (selectedEntityIDs.size === 0) { - return null; - } - return selectedEntityIDs.values().next().value; -} - -/** - * Returns true when the user is currently dragging the numeric slider control of the property - * @param propertyName - name of property - * @returns {boolean} currentlyDragging - */ -function isCurrentlyDraggingProperty(propertyName) { - return properties[propertyName] && properties[propertyName].dragging === true; -} - -const SUPPORTED_FALLBACK_TYPES = ['number', 'number-draggable', 'rect', 'vec3', 'vec2', 'color']; - -function getMultiplePropertyValue(originalPropertyName) { - // if this is a compound property name (i.e. animation.running) - // then split it by . up to 3 times to find property value - - let propertyData = null; - if (properties[originalPropertyName] !== undefined) { - propertyData = properties[originalPropertyName].data; - } - - let propertyValues = []; - let splitPropertyName = originalPropertyName.split('.'); - if (splitPropertyName.length > 1) { - let propertyGroupName = splitPropertyName[PROPERTY_NAME_DIVISION.GROUP]; - let propertyName = splitPropertyName[PROPERTY_NAME_DIVISION.PROPERTY]; - propertyValues = currentSelections.map(selection => { - let groupProperties = selection.properties[propertyGroupName]; - if (groupProperties === undefined || groupProperties[propertyName] === undefined) { - return undefined; - } - if (splitPropertyName.length === PROPERTY_NAME_DIVISION.SUB_PROPERTY + 1) { - let subPropertyName = splitPropertyName[PROPERTY_NAME_DIVISION.SUB_PROPERTY]; - return groupProperties[propertyName][subPropertyName]; - } else { - return groupProperties[propertyName]; - } - }); - } else { - propertyValues = currentSelections.map(selection => selection.properties[originalPropertyName]); - } - - if (propertyData !== null && propertyData.fallbackProperty !== undefined && - SUPPORTED_FALLBACK_TYPES.includes(propertyData.type)) { - - let fallbackMultiValue = null; - - for (let i = 0; i < propertyValues.length; ++i) { - let isPropertyNotNumber = false; - let propertyValue = propertyValues[i]; - if (propertyValue === undefined) { - continue; - } - switch (propertyData.type) { - case 'number': - case 'number-draggable': - isPropertyNotNumber = isNaN(propertyValue) || propertyValue === null; - break; - case 'rect': - case 'vec3': - case 'vec2': - isPropertyNotNumber = isNaN(propertyValue.x) || propertyValue.x === null; - break; - case 'color': - isPropertyNotNumber = isNaN(propertyValue.red) || propertyValue.red === null; - break; - } - if (isPropertyNotNumber) { - if (fallbackMultiValue === null) { - fallbackMultiValue = getMultiplePropertyValue(propertyData.fallbackProperty); - } - propertyValues[i] = fallbackMultiValue.values[i]; - } - } - } - - const firstValue = propertyValues[0]; - const isMultiDiffValue = !propertyValues.every((x) => deepEqual(firstValue, x)); - - if (isMultiDiffValue) { - return { - value: undefined, - values: propertyValues, - isMultiDiffValue: true - } - } - - return { - value: propertyValues[0], - values: propertyValues, - isMultiDiffValue: false - }; -} - -/** - * Retrieve more detailed info for differing Numeric MultiplePropertyValue - * @param multiplePropertyValue - input multiplePropertyValue - * @param propertyData - * @returns {{keys: *[], propertyComponentDiff, averagePerPropertyComponent}} - */ -function getDetailedNumberMPVDiff(multiplePropertyValue, propertyData) { - let detailedValues = {}; - // Fixed numbers can't be easily averaged since they're strings, so lets keep an array of unmodified numbers - let unmodifiedValues = {}; - const DEFAULT_KEY = 0; - let uniqueKeys = new Set([]); - multiplePropertyValue.values.forEach(function(propertyValue) { - if (typeof propertyValue === "object") { - Object.entries(propertyValue).forEach(function([key, value]) { - if (!uniqueKeys.has(key)) { - uniqueKeys.add(key); - detailedValues[key] = []; - unmodifiedValues[key] = []; - } - detailedValues[key].push(applyInputNumberPropertyModifiers(value, propertyData)); - unmodifiedValues[key].push(value); - }); - } else { - if (!uniqueKeys.has(DEFAULT_KEY)) { - uniqueKeys.add(DEFAULT_KEY); - detailedValues[DEFAULT_KEY] = []; - unmodifiedValues[DEFAULT_KEY] = []; - } - detailedValues[DEFAULT_KEY].push(applyInputNumberPropertyModifiers(propertyValue, propertyData)); - unmodifiedValues[DEFAULT_KEY].push(propertyValue); - } - }); - let keys = [...uniqueKeys]; - - let propertyComponentDiff = {}; - Object.entries(detailedValues).forEach(function([key, value]) { - propertyComponentDiff[key] = [...new Set(value)].length > 1; - }); - - let averagePerPropertyComponent = {}; - Object.entries(unmodifiedValues).forEach(function([key, value]) { - let average = value.reduce((a, b) => a + b) / value.length; - averagePerPropertyComponent[key] = applyInputNumberPropertyModifiers(average, propertyData); - }); - - return { - keys, - propertyComponentDiff, - averagePerPropertyComponent, - }; -} - -function getDetailedSubPropertyMPVDiff(multiplePropertyValue, subPropertyName) { - let isChecked = false; - let checkedValues = multiplePropertyValue.values.map((value) => value.split(",").includes(subPropertyName)); - let isMultiDiff = !checkedValues.every(value => value === checkedValues[0]); - if (!isMultiDiff) { - isChecked = checkedValues[0]; - } - return { - isChecked, - isMultiDiff - } -} - -function updateVisibleSpaceModeProperties() { - for (let propertyID in properties) { - if (properties.hasOwnProperty(propertyID)) { - let property = properties[propertyID]; - let propertySpaceMode = property.spaceMode; - let elProperty = properties[propertyID].elContainer; - if (propertySpaceMode !== PROPERTY_SPACE_MODE.ALL && propertySpaceMode !== currentSpaceMode) { - elProperty.classList.add('spacemode-hidden'); - } else { - elProperty.classList.remove('spacemode-hidden'); - } - } - } -} - -/** - * PROPERTY UPDATE FUNCTIONS - */ - -function createPropertyUpdateObject(originalPropertyName, propertyValue) { - let propertyUpdate = {}; - // if this is a compound property name (i.e. animation.running) then split it by . up to 3 times - let splitPropertyName = originalPropertyName.split('.'); - if (splitPropertyName.length > 1) { - let propertyGroupName = splitPropertyName[PROPERTY_NAME_DIVISION.GROUP]; - let propertyName = splitPropertyName[PROPERTY_NAME_DIVISION.PROPERTY]; - propertyUpdate[propertyGroupName] = {}; - if (splitPropertyName.length === PROPERTY_NAME_DIVISION.SUB_PROPERTY + 1) { - let subPropertyName = splitPropertyName[PROPERTY_NAME_DIVISION.SUB_PROPERTY]; - propertyUpdate[propertyGroupName][propertyName] = {}; - propertyUpdate[propertyGroupName][propertyName][subPropertyName] = propertyValue; - } else { - propertyUpdate[propertyGroupName][propertyName] = propertyValue; - } - } else { - propertyUpdate[originalPropertyName] = propertyValue; - } - return propertyUpdate; -} - -function updateProperty(originalPropertyName, propertyValue, isParticleProperty) { - let propertyUpdate = createPropertyUpdateObject(originalPropertyName, propertyValue); - - // queue up particle property changes with the debounced sync to avoid - // causing particle emitting to reset excessively with each value change - if (isParticleProperty) { - Object.keys(propertyUpdate).forEach(function (propertyUpdateKey) { - particlePropertyUpdates[propertyUpdateKey] = propertyUpdate[propertyUpdateKey]; - }); - particleSyncDebounce(); - } else { - // only update the entity property value itself if in the middle of dragging - // prevent undo command push, saving new property values, and property update - // callback until drag is complete (additional update sent via dragEnd callback) - let onlyUpdateEntity = isCurrentlyDraggingProperty(originalPropertyName); - updateProperties(propertyUpdate, onlyUpdateEntity); - } -} - -let particleSyncDebounce = _.debounce(function () { - updateProperties(particlePropertyUpdates); - particlePropertyUpdates = {}; -}, DEBOUNCE_TIMEOUT); - -function updateProperties(propertiesToUpdate, onlyUpdateEntity) { - if (onlyUpdateEntity === undefined) { - onlyUpdateEntity = false; - } - EventBridge.emitWebEvent(JSON.stringify({ - ids: [...selectedEntityIDs], - type: "update", - properties: propertiesToUpdate, - onlyUpdateEntities: onlyUpdateEntity - })); -} - -function updateMultiDiffProperties(propertiesMapToUpdate, onlyUpdateEntity) { - if (onlyUpdateEntity === undefined) { - onlyUpdateEntity = false; - } - EventBridge.emitWebEvent(JSON.stringify({ - type: "update", - propertiesMap: propertiesMapToUpdate, - onlyUpdateEntities: onlyUpdateEntity - })); -} - -function createEmitTextPropertyUpdateFunction(property) { - return function() { - property.elInput.classList.remove('multi-diff'); - updateProperty(property.name, this.value, property.isParticleProperty); - }; -} - -function createEmitCheckedPropertyUpdateFunction(property) { - return function() { - updateProperty(property.name, property.data.inverse ? !this.checked : this.checked, property.isParticleProperty); - }; -} - -function createDragStartFunction(property) { - return function() { - property.dragging = true; - }; -} - -function createDragEndFunction(property) { - return function() { - property.dragging = false; - - if (this.multiDiffModeEnabled) { - let propertyMultiValue = getMultiplePropertyValue(property.name); - let updateObjects = []; - const selectedEntityIDsArray = [...selectedEntityIDs]; - - for (let i = 0; i < selectedEntityIDsArray.length; ++i) { - let entityID = selectedEntityIDsArray[i]; - updateObjects.push({ - entityIDs: [entityID], - properties: createPropertyUpdateObject(property.name, propertyMultiValue.values[i]), - }); - } - - // send a full updateMultiDiff post-dragging to count as an action in the undo stack - updateMultiDiffProperties(updateObjects); - } else { - // send an additional update post-dragging to consider whole property change from dragStart to dragEnd to be 1 action - this.valueChangeFunction(); - } - }; -} - -function createEmitNumberPropertyUpdateFunction(property) { - return function() { - let value = parseFloat(applyOutputNumberPropertyModifiers(parseFloat(this.value), property.data)); - updateProperty(property.name, value, property.isParticleProperty); - }; -} - -function createEmitNumberPropertyComponentUpdateFunction(property, propertyComponent) { - return function() { - let propertyMultiValue = getMultiplePropertyValue(property.name); - let value = parseFloat(applyOutputNumberPropertyModifiers(parseFloat(this.value), property.data)); - - if (propertyMultiValue.isMultiDiffValue) { - let updateObjects = []; - const selectedEntityIDsArray = [...selectedEntityIDs]; - - for (let i = 0; i < selectedEntityIDsArray.length; ++i) { - let entityID = selectedEntityIDsArray[i]; - - let propertyObject = propertyMultiValue.values[i]; - propertyObject[propertyComponent] = value; - - let updateObject = createPropertyUpdateObject(property.name, propertyObject); - updateObjects.push({ - entityIDs: [entityID], - properties: updateObject, - }); - - mergeDeep(currentSelections[i].properties, updateObject); - } - - // only update the entity property value itself if in the middle of dragging - // prevent undo command push, saving new property values, and property update - // callback until drag is complete (additional update sent via dragEnd callback) - let onlyUpdateEntity = isCurrentlyDraggingProperty(property.name); - updateMultiDiffProperties(updateObjects, onlyUpdateEntity); - } else { - let propertyValue = propertyMultiValue.value; - propertyValue[propertyComponent] = value; - updateProperty(property.name, propertyValue, property.isParticleProperty); - } - }; -} - -function createEmitColorPropertyUpdateFunction(property) { - return function() { - emitColorPropertyUpdate(property.name, property.elNumberR.elInput.value, property.elNumberG.elInput.value, - property.elNumberB.elInput.value, property.isParticleProperty); - }; -} - -function emitColorPropertyUpdate(propertyName, red, green, blue, isParticleProperty) { - let newValue = { - red: red, - green: green, - blue: blue - }; - updateProperty(propertyName, newValue, isParticleProperty); -} - -function toggleBooleanCSV(inputCSV, property, enable) { - let values = inputCSV.split(","); - if (enable && !values.includes(property)) { - values.push(property); - } else if (!enable && values.includes(property)) { - values = values.filter(value => value !== property); - } - return values.join(","); -} - -function updateCheckedSubProperty(propertyName, propertyMultiValue, subPropertyElement, subPropertyString, isParticleProperty) { - if (propertyMultiValue.isMultiDiffValue) { - let updateObjects = []; - const selectedEntityIDsArray = [...selectedEntityIDs]; - - for (let i = 0; i < selectedEntityIDsArray.length; ++i) { - let newValue = toggleBooleanCSV(propertyMultiValue.values[i], subPropertyString, subPropertyElement.checked); - updateObjects.push({ - entityIDs: [selectedEntityIDsArray[i]], - properties: createPropertyUpdateObject(propertyName, newValue), - }); - } - - updateMultiDiffProperties(updateObjects); - } else { - updateProperty(propertyName, toggleBooleanCSV(propertyMultiValue.value, subPropertyString, subPropertyElement.checked), - isParticleProperty); - } -} - -/** - * PROPERTY ELEMENT CREATION FUNCTIONS - */ - -function createStringProperty(property, elProperty) { - let elementID = property.elementID; - let propertyData = property.data; - - elProperty.className = "text"; - - let elInput = createElementFromHTML(` - - `); - - - elInput.addEventListener('change', createEmitTextPropertyUpdateFunction(property)); - if (propertyData.onChange !== undefined) { - elInput.addEventListener('change', propertyData.onChange); - } - - - let elMultiDiff = document.createElement('span'); - elMultiDiff.className = "multi-diff"; - - elProperty.appendChild(elInput); - elProperty.appendChild(elMultiDiff); - - if (propertyData.buttons !== undefined) { - addButtons(elProperty, elementID, propertyData.buttons, false); - } - - return elInput; -} - -function createBoolProperty(property, elProperty) { - let propertyName = property.name; - let elementID = property.elementID; - let propertyData = property.data; - - elProperty.className = "checkbox"; - - if (propertyData.glyph !== undefined) { - let elSpan = document.createElement('span'); - elSpan.innerHTML = propertyData.glyph; - elSpan.className = 'icon'; - elProperty.appendChild(elSpan); - } - - let elInput = document.createElement('input'); - elInput.setAttribute("id", elementID); - elInput.setAttribute("type", "checkbox"); - - elProperty.appendChild(elInput); - elProperty.appendChild(createElementFromHTML(``)); - - let subPropertyOf = propertyData.subPropertyOf; - if (subPropertyOf !== undefined) { - elInput.addEventListener('change', function() { - let subPropertyMultiValue = getMultiplePropertyValue(subPropertyOf); - - updateCheckedSubProperty(subPropertyOf, - subPropertyMultiValue, - elInput, propertyName, property.isParticleProperty); - }); - } else { - elInput.addEventListener('change', createEmitCheckedPropertyUpdateFunction(property)); - } - - return elInput; -} - -function createNumberProperty(property, elProperty) { - let elementID = property.elementID; - let propertyData = property.data; - - elProperty.className = "text"; - - let elInput = createElementFromHTML(` - - `); - - if (propertyData.min !== undefined) { - elInput.setAttribute("min", propertyData.min); - } - if (propertyData.max !== undefined) { - elInput.setAttribute("max", propertyData.max); - } - if (propertyData.step !== undefined) { - elInput.setAttribute("step", propertyData.step); - } - if (propertyData.defaultValue !== undefined) { - elInput.value = propertyData.defaultValue; - } - - elInput.addEventListener('change', createEmitNumberPropertyUpdateFunction(property)); - - let elMultiDiff = document.createElement('span'); - elMultiDiff.className = "multi-diff"; - - elProperty.appendChild(elInput); - elProperty.appendChild(elMultiDiff); - - if (propertyData.buttons !== undefined) { - addButtons(elProperty, elementID, propertyData.buttons, false); - } - - return elInput; -} - -function updateNumberMinMax(property) { - let elInput = property.elInput; - let min = property.data.min; - let max = property.data.max; - if (min !== undefined) { - elInput.setAttribute("min", min); - } - if (max !== undefined) { - elInput.setAttribute("max", max); - } -} - -/** - * - * @param {object} property - property update on step - * @param {string} [propertyComponent] - propertyComponent to update on step (e.g. enter 'x' to just update position.x) - * @returns {Function} - */ -function createMultiDiffStepFunction(property, propertyComponent) { - return function(step, shouldAddToUndoHistory) { - if (shouldAddToUndoHistory === undefined) { - shouldAddToUndoHistory = false; - } - - let propertyMultiValue = getMultiplePropertyValue(property.name); - if (!propertyMultiValue.isMultiDiffValue) { - console.log("setMultiDiffStepFunction is only supposed to be called in MultiDiff mode."); - return; - } - - let multiplier = property.data.multiplier !== undefined ? property.data.multiplier : 1; - - let applyDelta = step * multiplier; - - if (selectedEntityIDs.size !== propertyMultiValue.values.length) { - console.log("selectedEntityIDs and propertyMultiValue got out of sync."); - return; - } - let updateObjects = []; - const selectedEntityIDsArray = [...selectedEntityIDs]; - - for (let i = 0; i < selectedEntityIDsArray.length; ++i) { - let entityID = selectedEntityIDsArray[i]; - - let updatedValue; - if (propertyComponent !== undefined) { - let objectToUpdate = propertyMultiValue.values[i]; - objectToUpdate[propertyComponent] += applyDelta; - updatedValue = objectToUpdate; - } else { - updatedValue = propertyMultiValue.values[i] + applyDelta; - } - let propertiesUpdate = createPropertyUpdateObject(property.name, updatedValue); - updateObjects.push({ - entityIDs: [entityID], - properties: propertiesUpdate - }); - // We need to store these so that we can send a full update on the dragEnd - mergeDeep(currentSelections[i].properties, propertiesUpdate); - } - - updateMultiDiffProperties(updateObjects, !shouldAddToUndoHistory); - } -} - -function createNumberDraggableProperty(property, elProperty) { - let elementID = property.elementID; - let propertyData = property.data; - - elProperty.className += " draggable-number-container"; - - let dragStartFunction = createDragStartFunction(property); - let dragEndFunction = createDragEndFunction(property); - let elDraggableNumber = new DraggableNumber(propertyData.min, propertyData.max, propertyData.step, - propertyData.decimals, dragStartFunction, dragEndFunction); - - let defaultValue = propertyData.defaultValue; - if (defaultValue !== undefined) { - elDraggableNumber.elInput.value = defaultValue; - } - - let valueChangeFunction = createEmitNumberPropertyUpdateFunction(property); - elDraggableNumber.setValueChangeFunction(valueChangeFunction); - - elDraggableNumber.setMultiDiffStepFunction(createMultiDiffStepFunction(property)); - - elDraggableNumber.elInput.setAttribute("id", elementID); - elProperty.appendChild(elDraggableNumber.elDiv); - - if (propertyData.buttons !== undefined) { - addButtons(elDraggableNumber.elDiv, elementID, propertyData.buttons, false); - } - - return elDraggableNumber; -} - -function updateNumberDraggableMinMax(property) { - let propertyData = property.data; - property.elNumber.updateMinMax(propertyData.min, propertyData.max); -} - -function createRectProperty(property, elProperty) { - let propertyData = property.data; - - elProperty.className = "rect"; - - let elXYRow = document.createElement('div'); - elXYRow.className = "rect-row fstuple"; - elProperty.appendChild(elXYRow); - - let elWidthHeightRow = document.createElement('div'); - elWidthHeightRow.className = "rect-row fstuple"; - elProperty.appendChild(elWidthHeightRow); - - - let elNumberX = createTupleNumberInput(property, propertyData.subLabels[RECT_ELEMENTS.X_NUMBER]); - let elNumberY = createTupleNumberInput(property, propertyData.subLabels[RECT_ELEMENTS.Y_NUMBER]); - let elNumberWidth = createTupleNumberInput(property, propertyData.subLabels[RECT_ELEMENTS.WIDTH_NUMBER]); - let elNumberHeight = createTupleNumberInput(property, propertyData.subLabels[RECT_ELEMENTS.HEIGHT_NUMBER]); - - elXYRow.appendChild(elNumberX.elDiv); - elXYRow.appendChild(elNumberY.elDiv); - elWidthHeightRow.appendChild(elNumberWidth.elDiv); - elWidthHeightRow.appendChild(elNumberHeight.elDiv); - - elNumberX.setValueChangeFunction(createEmitNumberPropertyComponentUpdateFunction(property, 'x')); - elNumberY.setValueChangeFunction(createEmitNumberPropertyComponentUpdateFunction(property, 'y')); - elNumberWidth.setValueChangeFunction(createEmitNumberPropertyComponentUpdateFunction(property, 'width')); - elNumberHeight.setValueChangeFunction(createEmitNumberPropertyComponentUpdateFunction(property, 'height')); - - elNumberX.setMultiDiffStepFunction(createMultiDiffStepFunction(property, 'x')); - elNumberY.setMultiDiffStepFunction(createMultiDiffStepFunction(property, 'y')); - elNumberX.setMultiDiffStepFunction(createMultiDiffStepFunction(property, 'width')); - elNumberY.setMultiDiffStepFunction(createMultiDiffStepFunction(property, 'height')); - - let elResult = []; - elResult[RECT_ELEMENTS.X_NUMBER] = elNumberX; - elResult[RECT_ELEMENTS.Y_NUMBER] = elNumberY; - elResult[RECT_ELEMENTS.WIDTH_NUMBER] = elNumberWidth; - elResult[RECT_ELEMENTS.HEIGHT_NUMBER] = elNumberHeight; - return elResult; -} - -function updateRectMinMax(property) { - let min = property.data.min; - let max = property.data.max; - property.elNumberX.updateMinMax(min, max); - property.elNumberY.updateMinMax(min, max); - property.elNumberWidth.updateMinMax(min, max); - property.elNumberHeight.updateMinMax(min, max); -} - -function createVec3Property(property, elProperty) { - let propertyData = property.data; - - elProperty.className = propertyData.vec3Type + " fstuple"; - - let elNumberX = createTupleNumberInput(property, propertyData.subLabels[VECTOR_ELEMENTS.X_NUMBER]); - let elNumberY = createTupleNumberInput(property, propertyData.subLabels[VECTOR_ELEMENTS.Y_NUMBER]); - let elNumberZ = createTupleNumberInput(property, propertyData.subLabels[VECTOR_ELEMENTS.Z_NUMBER]); - elProperty.appendChild(elNumberX.elDiv); - elProperty.appendChild(elNumberY.elDiv); - elProperty.appendChild(elNumberZ.elDiv); - - elNumberX.setValueChangeFunction(createEmitNumberPropertyComponentUpdateFunction(property, 'x')); - elNumberY.setValueChangeFunction(createEmitNumberPropertyComponentUpdateFunction(property, 'y')); - elNumberZ.setValueChangeFunction(createEmitNumberPropertyComponentUpdateFunction(property, 'z')); - - elNumberX.setMultiDiffStepFunction(createMultiDiffStepFunction(property, 'x')); - elNumberY.setMultiDiffStepFunction(createMultiDiffStepFunction(property, 'y')); - elNumberZ.setMultiDiffStepFunction(createMultiDiffStepFunction(property, 'z')); - - let elResult = []; - elResult[VECTOR_ELEMENTS.X_NUMBER] = elNumberX; - elResult[VECTOR_ELEMENTS.Y_NUMBER] = elNumberY; - elResult[VECTOR_ELEMENTS.Z_NUMBER] = elNumberZ; - return elResult; -} - -function createVec2Property(property, elProperty) { - let propertyData = property.data; - - elProperty.className = propertyData.vec2Type + " fstuple"; - - let elTuple = document.createElement('div'); - elTuple.className = "tuple"; - - elProperty.appendChild(elTuple); - - let elNumberX = createTupleNumberInput(property, propertyData.subLabels[VECTOR_ELEMENTS.X_NUMBER]); - let elNumberY = createTupleNumberInput(property, propertyData.subLabels[VECTOR_ELEMENTS.Y_NUMBER]); - elProperty.appendChild(elNumberX.elDiv); - elProperty.appendChild(elNumberY.elDiv); - - elNumberX.setValueChangeFunction(createEmitNumberPropertyComponentUpdateFunction(property, 'x')); - elNumberY.setValueChangeFunction(createEmitNumberPropertyComponentUpdateFunction(property, 'y')); - - elNumberX.setMultiDiffStepFunction(createMultiDiffStepFunction(property, 'x')); - elNumberY.setMultiDiffStepFunction(createMultiDiffStepFunction(property, 'y')); - - let elResult = []; - elResult[VECTOR_ELEMENTS.X_NUMBER] = elNumberX; - elResult[VECTOR_ELEMENTS.Y_NUMBER] = elNumberY; - return elResult; -} - -function updateVectorMinMax(property) { - let min = property.data.min; - let max = property.data.max; - property.elNumberX.updateMinMax(min, max); - property.elNumberY.updateMinMax(min, max); - if (property.elNumberZ) { - property.elNumberZ.updateMinMax(min, max); - } -} - -function createColorProperty(property, elProperty) { - let propertyName = property.name; - let elementID = property.elementID; - let propertyData = property.data; - - elProperty.className += " rgb fstuple"; - - let elColorPicker = document.createElement('div'); - elColorPicker.className = "color-picker"; - elColorPicker.setAttribute("id", elementID); - - let elTuple = document.createElement('div'); - elTuple.className = "tuple"; - - elProperty.appendChild(elColorPicker); - elProperty.appendChild(elTuple); - - if (propertyData.min === undefined) { - propertyData.min = COLOR_MIN; - } - if (propertyData.max === undefined) { - propertyData.max = COLOR_MAX; - } - if (propertyData.step === undefined) { - propertyData.step = COLOR_STEP; - } - - let elNumberR = createTupleNumberInput(property, "red"); - let elNumberG = createTupleNumberInput(property, "green"); - let elNumberB = createTupleNumberInput(property, "blue"); - elTuple.appendChild(elNumberR.elDiv); - elTuple.appendChild(elNumberG.elDiv); - elTuple.appendChild(elNumberB.elDiv); - - let valueChangeFunction = createEmitColorPropertyUpdateFunction(property); - elNumberR.setValueChangeFunction(valueChangeFunction); - elNumberG.setValueChangeFunction(valueChangeFunction); - elNumberB.setValueChangeFunction(valueChangeFunction); - - let colorPickerID = "#" + elementID; - colorPickers[colorPickerID] = $(colorPickerID).colpick({ - colorScheme: 'dark', - layout: 'rgbhex', - color: '000000', - submit: false, // We don't want to have a submission button - onShow: function(colpick) { - // The original color preview within the picker needs to be updated on show because - // prior to the picker being shown we don't have access to the selections' starting color. - colorPickers[colorPickerID].colpickSetColor({ - "r": elNumberR.elInput.value, - "g": elNumberG.elInput.value, - "b": elNumberB.elInput.value - }); - - // Set the color picker active after setting the color, otherwise an update will be sent on open. - $(colorPickerID).attr('active', 'true'); - }, - onHide: function(colpick) { - $(colorPickerID).attr('active', 'false'); - }, - onChange: function(hsb, hex, rgb, el) { - $(el).css('background-color', '#' + hex); - if ($(colorPickerID).attr('active') === 'true') { - emitColorPropertyUpdate(propertyName, rgb.r, rgb.g, rgb.b); - } - } - }); - - let elResult = []; - elResult[COLOR_ELEMENTS.COLOR_PICKER] = elColorPicker; - elResult[COLOR_ELEMENTS.RED_NUMBER] = elNumberR; - elResult[COLOR_ELEMENTS.GREEN_NUMBER] = elNumberG; - elResult[COLOR_ELEMENTS.BLUE_NUMBER] = elNumberB; - return elResult; -} - -function createDropdownProperty(property, propertyID, elProperty) { - let elementID = property.elementID; - let propertyData = property.data; - - elProperty.className = "dropdown"; - - let elInput = document.createElement('select'); - elInput.setAttribute("id", elementID); - elInput.setAttribute("propertyID", propertyID); - - for (let optionKey in propertyData.options) { - let option = document.createElement('option'); - option.value = optionKey; - option.text = propertyData.options[optionKey]; - elInput.add(option); - } - - elInput.addEventListener('change', createEmitTextPropertyUpdateFunction(property)); - - elProperty.appendChild(elInput); - - return elInput; -} - -function createTextareaProperty(property, elProperty) { - let elementID = property.elementID; - let propertyData = property.data; - - elProperty.className = "textarea"; - - let elInput = document.createElement('textarea'); - elInput.setAttribute("id", elementID); - if (propertyData.readOnly) { - elInput.readOnly = true; - } - - elInput.addEventListener('change', createEmitTextPropertyUpdateFunction(property)); - - let elMultiDiff = document.createElement('span'); - elMultiDiff.className = "multi-diff"; - - elProperty.appendChild(elInput); - elProperty.appendChild(elMultiDiff); - - if (propertyData.buttons !== undefined) { - addButtons(elProperty, elementID, propertyData.buttons, true); - } - - return elInput; -} - -function createIconProperty(property, elProperty) { - let elementID = property.elementID; - - elProperty.className = "value"; - - let elSpan = document.createElement('span'); - elSpan.setAttribute("id", elementID + "-icon"); - elSpan.className = 'icon'; - - elProperty.appendChild(elSpan); - - return elSpan; -} - -function createTextureProperty(property, elProperty) { - let elementID = property.elementID; - - elProperty.className = "texture"; - - let elDiv = document.createElement("div"); - let elImage = document.createElement("img"); - elDiv.className = "texture-image no-texture"; - elDiv.appendChild(elImage); - - let elInput = document.createElement('input'); - elInput.setAttribute("id", elementID); - elInput.setAttribute("type", "text"); - - let imageLoad = function(url) { - elDiv.style.display = null; - if (url.slice(0, 5).toLowerCase() === "atp:/") { - elImage.src = ""; - elImage.style.display = "none"; - elDiv.classList.remove("with-texture"); - elDiv.classList.remove("no-texture"); - elDiv.classList.add("no-preview"); - } else if (url.length > 0) { - elDiv.classList.remove("no-texture"); - elDiv.classList.remove("no-preview"); - elDiv.classList.add("with-texture"); - elImage.src = url; - elImage.style.display = "block"; - } else { - elImage.src = ""; - elImage.style.display = "none"; - elDiv.classList.remove("with-texture"); - elDiv.classList.remove("no-preview"); - elDiv.classList.add("no-texture"); - } - }; - elInput.imageLoad = imageLoad; - elInput.setMultipleValues = function() { - elDiv.style.display = "none"; - }; - elInput.addEventListener('change', createEmitTextPropertyUpdateFunction(property)); - elInput.addEventListener('change', function(ev) { - imageLoad(ev.target.value); - }); - - elProperty.appendChild(elInput); - let elMultiDiff = document.createElement('span'); - elMultiDiff.className = "multi-diff"; - elProperty.appendChild(elMultiDiff); - elProperty.appendChild(elDiv); - - let elResult = []; - elResult[TEXTURE_ELEMENTS.IMAGE] = elImage; - elResult[TEXTURE_ELEMENTS.TEXT_INPUT] = elInput; - return elResult; -} - -function createButtonsProperty(property, elProperty) { - let elementID = property.elementID; - let propertyData = property.data; - - elProperty.className = "text"; - - if (propertyData.buttons !== undefined) { - addButtons(elProperty, elementID, propertyData.buttons, false); - } - - return elProperty; -} - -function createDynamicMultiselectProperty(property, elProperty) { - let elementID = property.elementID; - let propertyData = property.data; - - elProperty.className = "dynamic-multiselect"; - - let elDivOptions = document.createElement('div'); - elDivOptions.setAttribute("id", elementID + "-options"); - elDivOptions.style = "overflow-y:scroll;max-height:160px;"; - - let elDivButtons = document.createElement('div'); - elDivButtons.setAttribute("id", elDivOptions.getAttribute("id") + "-buttons"); - - let elLabel = document.createElement('label'); - elLabel.innerText = "No Options"; - elDivOptions.appendChild(elLabel); - - let buttons = [ { id: "selectAll", label: "Select All", className: "black", onClick: selectAllMaterialTarget }, - { id: "clearAll", label: "Clear All", className: "black", onClick: clearAllMaterialTarget } ]; - addButtons(elDivButtons, elementID, buttons, false); - - elProperty.appendChild(elDivOptions); - elProperty.appendChild(elDivButtons); - - return elDivOptions; -} - -function resetDynamicMultiselectProperty(elDivOptions) { - let elInputs = elDivOptions.getElementsByTagName("input"); - while (elInputs.length > 0) { - let elDivOption = elInputs[0].parentNode; - elDivOption.parentNode.removeChild(elDivOption); - } - elDivOptions.firstChild.style.display = null; // show "No Options" text - elDivOptions.parentNode.lastChild.style.display = "none"; // hide Select/Clear all buttons -} - -function createTupleNumberInput(property, subLabel) { - let propertyElementID = property.elementID; - let propertyData = property.data; - let elementID = propertyElementID + "-" + subLabel.toLowerCase(); - - let elLabel = document.createElement('label'); - elLabel.className = "sublabel " + subLabel; - elLabel.innerText = subLabel[0].toUpperCase() + subLabel.slice(1); - elLabel.setAttribute("for", elementID); - elLabel.style.visibility = "visible"; - - let dragStartFunction = createDragStartFunction(property); - let dragEndFunction = createDragEndFunction(property); - let elDraggableNumber = new DraggableNumber(propertyData.min, propertyData.max, propertyData.step, - propertyData.decimals, dragStartFunction, dragEndFunction); - elDraggableNumber.elInput.setAttribute("id", elementID); - elDraggableNumber.elDiv.className += " fstuple"; - elDraggableNumber.elDiv.insertBefore(elLabel, elDraggableNumber.elLeftArrow); - - return elDraggableNumber; -} - -function addButtons(elProperty, propertyID, buttons, newRow) { - let elDiv = document.createElement('div'); - elDiv.className = "row"; - - buttons.forEach(function(button) { - let elButton = document.createElement('input'); - elButton.className = button.className; - elButton.setAttribute("type", "button"); - elButton.setAttribute("id", propertyID + "-button-" + button.id); - elButton.setAttribute("value", button.label); - elButton.addEventListener("click", button.onClick); - if (newRow) { - elDiv.appendChild(elButton); - } else { - elProperty.appendChild(elButton); - } - }); - - if (newRow) { - elProperty.appendChild(document.createElement('br')); - elProperty.appendChild(elDiv); - } -} - -function createProperty(propertyData, propertyElementID, propertyName, propertyID, elProperty) { - let property = { - data: propertyData, - elementID: propertyElementID, - name: propertyName, - elProperty: elProperty, - }; - let propertyType = propertyData.type; - - switch (propertyType) { - case 'string': { - property.elInput = createStringProperty(property, elProperty); - break; - } - case 'bool': { - property.elInput = createBoolProperty(property, elProperty); - break; - } - case 'number': { - property.elInput = createNumberProperty(property, elProperty); - break; - } - case 'number-draggable': { - property.elNumber = createNumberDraggableProperty(property, elProperty); - break; - } - case 'rect': { - let elRect = createRectProperty(property, elProperty); - property.elNumberX = elRect[RECT_ELEMENTS.X_NUMBER]; - property.elNumberY = elRect[RECT_ELEMENTS.Y_NUMBER]; - property.elNumberWidth = elRect[RECT_ELEMENTS.WIDTH_NUMBER]; - property.elNumberHeight = elRect[RECT_ELEMENTS.HEIGHT_NUMBER]; - break; - } - case 'vec3': { - let elVec3 = createVec3Property(property, elProperty); - property.elNumberX = elVec3[VECTOR_ELEMENTS.X_NUMBER]; - property.elNumberY = elVec3[VECTOR_ELEMENTS.Y_NUMBER]; - property.elNumberZ = elVec3[VECTOR_ELEMENTS.Z_NUMBER]; - break; - } - case 'vec2': { - let elVec2 = createVec2Property(property, elProperty); - property.elNumberX = elVec2[VECTOR_ELEMENTS.X_NUMBER]; - property.elNumberY = elVec2[VECTOR_ELEMENTS.Y_NUMBER]; - break; - } - case 'color': { - let elColor = createColorProperty(property, elProperty); - property.elColorPicker = elColor[COLOR_ELEMENTS.COLOR_PICKER]; - property.elNumberR = elColor[COLOR_ELEMENTS.RED_NUMBER]; - property.elNumberG = elColor[COLOR_ELEMENTS.GREEN_NUMBER]; - property.elNumberB = elColor[COLOR_ELEMENTS.BLUE_NUMBER]; - break; - } - case 'dropdown': { - property.elInput = createDropdownProperty(property, propertyID, elProperty); - break; - } - case 'textarea': { - property.elInput = createTextareaProperty(property, elProperty); - break; - } - case 'icon': { - property.elSpan = createIconProperty(property, elProperty); - break; - } - case 'texture': { - let elTexture = createTextureProperty(property, elProperty); - property.elImage = elTexture[TEXTURE_ELEMENTS.IMAGE]; - property.elInput = elTexture[TEXTURE_ELEMENTS.TEXT_INPUT]; - break; - } - case 'buttons': { - property.elProperty = createButtonsProperty(property, elProperty); - break; - } - case 'dynamic-multiselect': { - property.elDivOptions = createDynamicMultiselectProperty(property, elProperty); - break; - } - case 'placeholder': - case 'sub-header': { - break; - } - default: { - console.log("EntityProperties - Unknown property type " + - propertyType + " set to property " + propertyID); - break; - } - } - - return property; -} - - -/** - * PROPERTY-SPECIFIC CALLBACKS - */ - -function parentIDChanged() { - if (currentSelections.length === 1 && currentSelections[0].properties.type === "Material") { - requestMaterialTarget(); - } -} - - -/** - * BUTTON CALLBACKS - */ - -function rescaleDimensions() { - EventBridge.emitWebEvent(JSON.stringify({ - type: "action", - action: "rescaleDimensions", - percentage: parseFloat(document.getElementById("property-scale").value) - })); -} - -function moveSelectionToGrid() { - EventBridge.emitWebEvent(JSON.stringify({ - type: "action", - action: "moveSelectionToGrid" - })); -} - -function moveAllToGrid() { - EventBridge.emitWebEvent(JSON.stringify({ - type: "action", - action: "moveAllToGrid" - })); -} - -function resetToNaturalDimensions() { - EventBridge.emitWebEvent(JSON.stringify({ - type: "action", - action: "resetToNaturalDimensions" - })); -} - -function reloadScripts() { - EventBridge.emitWebEvent(JSON.stringify({ - type: "action", - action: "reloadClientScripts" - })); -} - -function reloadServerScripts() { - // invalidate the current status (so that same-same updates can still be observed visually) - document.getElementById("property-serverScripts-status").innerText = PENDING_SCRIPT_STATUS; - EventBridge.emitWebEvent(JSON.stringify({ - type: "action", - action: "reloadServerScripts" - })); -} - -function copySkyboxURLToAmbientURL() { - let skyboxURL = getPropertyInputElement("skybox.url").value; - getPropertyInputElement("ambientLight.ambientURL").value = skyboxURL; - updateProperty("ambientLight.ambientURL", skyboxURL, false); -} - - -/** - * USER DATA FUNCTIONS - */ - -function clearUserData() { - let elUserData = getPropertyInputElement("userData"); - deleteJSONEditor(); - elUserData.value = ""; - showUserDataTextArea(); - showNewJSONEditorButton(); - hideSaveUserDataButton(); - updateProperty('userData', elUserData.value, false); -} - -function newJSONEditor() { - getPropertyInputElement("userData").classList.remove('multi-diff'); - deleteJSONEditor(); - createJSONEditor(); - let data = {}; - setEditorJSON(data); - hideUserDataTextArea(); - hideNewJSONEditorButton(); - showSaveUserDataButton(); -} - -/** - * @param {Set.} [entityIDsToUpdate] Entity IDs to update userData for. - */ -function saveUserData(entityIDsToUpdate) { - saveJSONUserData(true, entityIDsToUpdate); -} - -function setJSONError(property, isError) { - $("#property-"+ property + "-editor").toggleClass('error', isError); - let $propertyUserDataEditorStatus = $("#property-"+ property + "-editorStatus"); - $propertyUserDataEditorStatus.css('display', isError ? 'block' : 'none'); - $propertyUserDataEditorStatus.text(isError ? 'Invalid JSON code - look for red X in your code' : ''); -} - -/** - * @param {boolean} noUpdate - don't update the UI, but do send a property update. - * @param {Set.} [entityIDsToUpdate] - Entity IDs to update userData for. - */ -function setUserDataFromEditor(noUpdate, entityIDsToUpdate) { - let errorFound = false; - try { - editor.get(); - } catch (e) { - errorFound = true; - } - - setJSONError('userData', errorFound); - - if (errorFound) { - return; - } - - let text = editor.getText(); - if (noUpdate) { - EventBridge.emitWebEvent( - JSON.stringify({ - ids: [...entityIDsToUpdate], - type: "saveUserData", - properties: { - userData: text - } - }) - ); - } else { - updateProperty('userData', text, false); - } -} - -let editor = null; - -function createJSONEditor() { - let container = document.getElementById("property-userData-editor"); - let options = { - search: false, - mode: 'tree', - modes: ['code', 'tree'], - name: 'userData', - onError: function(e) { - alert('JSON editor:' + e); - }, - onChange: function() { - let currentJSONString = editor.getText(); - - if (currentJSONString === '{"":""}') { - return; - } - $('#property-userData-button-save').attr('disabled', false); - } - }; - editor = new JSONEditor(container, options); -} - -function showSaveUserDataButton() { - $('#property-userData-button-save').show(); -} - -function hideSaveUserDataButton() { - $('#property-userData-button-save').hide(); -} - -function disableSaveUserDataButton() { - $('#property-userData-button-save').attr('disabled', true); -} - -function showNewJSONEditorButton() { - $('#property-userData-button-edit').show(); -} - -function hideNewJSONEditorButton() { - $('#property-userData-button-edit').hide(); -} - -function showUserDataTextArea() { - $('#property-userData').show(); -} - -function hideUserDataTextArea() { - $('#property-userData').hide(); -} - -function hideUserDataSaved() { - $('#property-userData-saved').hide(); -} - -function showStaticUserData() { - if (editor !== null) { - let $propertyUserDataStatic = $('#property-userData-static'); - $propertyUserDataStatic.show(); - $propertyUserDataStatic.css('height', $('#property-userData-editor').height()); - $propertyUserDataStatic.text(editor.getText()); - } -} - -function removeStaticUserData() { - $('#property-userData-static').hide(); -} - -function setEditorJSON(json) { - editor.set(json); - if (editor.hasOwnProperty('expandAll')) { - editor.expandAll(); - } -} - -function deleteJSONEditor() { - if (editor !== null) { - setJSONError('userData', false); - editor.destroy(); - editor = null; - } -} - -let savedJSONTimer = null; - -/** - * @param {boolean} noUpdate - don't update the UI, but do send a property update. - * @param {Set.} [entityIDsToUpdate] Entity IDs to update userData for - */ -function saveJSONUserData(noUpdate, entityIDsToUpdate) { - setUserDataFromEditor(noUpdate, entityIDsToUpdate ? entityIDsToUpdate : selectedEntityIDs); - $('#property-userData-saved').show(); - $('#property-userData-button-save').attr('disabled', true); - if (savedJSONTimer !== null) { - clearTimeout(savedJSONTimer); - } - savedJSONTimer = setTimeout(function() { - hideUserDataSaved(); - }, EDITOR_TIMEOUT_DURATION); -} - - -/** - * MATERIAL DATA FUNCTIONS - */ - -function clearMaterialData() { - let elMaterialData = getPropertyInputElement("materialData"); - deleteJSONMaterialEditor(); - elMaterialData.value = ""; - showMaterialDataTextArea(); - showNewJSONMaterialEditorButton(); - hideSaveMaterialDataButton(); - updateProperty('materialData', elMaterialData.value, false); -} - -function newJSONMaterialEditor() { - getPropertyInputElement("materialData").classList.remove('multi-diff'); - deleteJSONMaterialEditor(); - createJSONMaterialEditor(); - let data = {}; - setMaterialEditorJSON(data); - hideMaterialDataTextArea(); - hideNewJSONMaterialEditorButton(); - showSaveMaterialDataButton(); -} - -function saveMaterialData() { - saveJSONMaterialData(true); -} - -/** - * @param {boolean} noUpdate - don't update the UI, but do send a property update. - * @param {Set.} [entityIDsToUpdate] - Entity IDs to update materialData for. - */ -function setMaterialDataFromEditor(noUpdate, entityIDsToUpdate) { - let errorFound = false; - try { - materialEditor.get(); - } catch (e) { - errorFound = true; - } - - setJSONError('materialData', errorFound); - - if (errorFound) { - return; - } - let text = materialEditor.getText(); - if (noUpdate) { - EventBridge.emitWebEvent( - JSON.stringify({ - ids: [...entityIDsToUpdate], - type: "saveMaterialData", - properties: { - materialData: text - } - }) - ); - } else { - updateProperty('materialData', text, false); - } -} - -let materialEditor = null; - -function createJSONMaterialEditor() { - let container = document.getElementById("property-materialData-editor"); - let options = { - search: false, - mode: 'tree', - modes: ['code', 'tree'], - name: 'materialData', - onError: function(e) { - alert('JSON editor:' + e); - }, - onChange: function() { - let currentJSONString = materialEditor.getText(); - - if (currentJSONString === '{"":""}') { - return; - } - $('#property-materialData-button-save').attr('disabled', false); - } - }; - materialEditor = new JSONEditor(container, options); -} - -function showSaveMaterialDataButton() { - $('#property-materialData-button-save').show(); -} - -function hideSaveMaterialDataButton() { - $('#property-materialData-button-save').hide(); -} - -function disableSaveMaterialDataButton() { - $('#property-materialData-button-save').attr('disabled', true); -} - -function showNewJSONMaterialEditorButton() { - $('#property-materialData-button-edit').show(); -} - -function hideNewJSONMaterialEditorButton() { - $('#property-materialData-button-edit').hide(); -} - -function showMaterialDataTextArea() { - $('#property-materialData').show(); -} - -function hideMaterialDataTextArea() { - $('#property-materialData').hide(); -} - -function hideMaterialDataSaved() { - $('#property-materialData-saved').hide(); -} - -function showStaticMaterialData() { - if (materialEditor !== null) { - let $propertyMaterialDataStatic = $('#property-materialData-static'); - $propertyMaterialDataStatic.show(); - $propertyMaterialDataStatic.css('height', $('#property-materialData-editor').height()); - $propertyMaterialDataStatic.text(materialEditor.getText()); - } -} - -function removeStaticMaterialData() { - $('#property-materialData-static').hide(); -} - -function setMaterialEditorJSON(json) { - materialEditor.set(json); - if (materialEditor.hasOwnProperty('expandAll')) { - materialEditor.expandAll(); - } -} - -function deleteJSONMaterialEditor() { - if (materialEditor !== null) { - setJSONError('materialData', false); - materialEditor.destroy(); - materialEditor = null; - } -} - -let savedMaterialJSONTimer = null; - -/** - * @param {boolean} noUpdate - don't update the UI, but do send a property update. - * @param {Set.} [entityIDsToUpdate] - Entity IDs to update materialData for. - */ -function saveJSONMaterialData(noUpdate, entityIDsToUpdate) { - setMaterialDataFromEditor(noUpdate, entityIDsToUpdate ? entityIDsToUpdate : selectedEntityIDs); - $('#property-materialData-saved').show(); - $('#property-materialData-button-save').attr('disabled', true); - if (savedMaterialJSONTimer !== null) { - clearTimeout(savedMaterialJSONTimer); - } - savedMaterialJSONTimer = setTimeout(function() { - hideMaterialDataSaved(); - }, EDITOR_TIMEOUT_DURATION); -} - -function bindAllNonJSONEditorElements() { - let inputs = $('input'); - let i; - for (i = 0; i < inputs.length; ++i) { - let input = inputs[i]; - let field = $(input); - // TODO FIXME: (JSHint) Functions declared within loops referencing - // an outer scoped variable may lead to confusing semantics. - field.on('focus', function(e) { - if (e.target.id === "property-userData-button-edit" || e.target.id === "property-userData-button-clear" || - e.target.id === "property-materialData-button-edit" || e.target.id === "property-materialData-button-clear") { - return; - } - if ($('#property-userData-editor').css('height') !== "0px") { - saveUserData(); - } - if ($('#property-materialData-editor').css('height') !== "0px") { - saveMaterialData(); - } - }); - } -} - - -/** - * DROPDOWN FUNCTIONS - */ - -function setDropdownText(dropdown) { - let lis = dropdown.parentNode.getElementsByTagName("li"); - let text = ""; - for (let i = 0; i < lis.length; ++i) { - if (String(lis[i].getAttribute("value")) === String(dropdown.value)) { - text = lis[i].textContent; - } - } - dropdown.firstChild.textContent = text; -} - -function toggleDropdown(event) { - let element = event.target; - if (element.nodeName !== "DT") { - element = element.parentNode; - } - element = element.parentNode; - let isDropped = element.getAttribute("dropped"); - element.setAttribute("dropped", isDropped !== "true" ? "true" : "false"); -} - -function closeAllDropdowns() { - let elDropdowns = document.querySelectorAll("div.dropdown > dl"); - for (let i = 0; i < elDropdowns.length; ++i) { - elDropdowns[i].setAttribute('dropped', 'false'); - } -} - -function setDropdownValue(event) { - let dt = event.target.parentNode.parentNode.previousSibling.previousSibling; - dt.value = event.target.getAttribute("value"); - dt.firstChild.textContent = event.target.textContent; - - dt.parentNode.setAttribute("dropped", "false"); - - let evt = document.createEvent("HTMLEvents"); - evt.initEvent("change", true, true); - dt.dispatchEvent(evt); -} - - -/** - * TEXTAREA FUNCTIONS - */ - -function setTextareaScrolling(element) { - let isScrolling = element.scrollHeight > element.offsetHeight; - element.setAttribute("scrolling", isScrolling ? "true" : "false"); -} - - -/** - * MATERIAL TARGET FUNCTIONS - */ - -function requestMaterialTarget() { - EventBridge.emitWebEvent(JSON.stringify({ - type: 'materialTargetRequest', - entityID: getFirstSelectedID(), - })); -} - -function setMaterialTargetData(materialTargetData) { - let elDivOptions = getPropertyInputElement("parentMaterialName"); - resetDynamicMultiselectProperty(elDivOptions); - - if (materialTargetData === undefined) { - return; - } - - elDivOptions.firstChild.style.display = "none"; // hide "No Options" text - elDivOptions.parentNode.lastChild.style.display = null; // show Select/Clear all buttons - - let numMeshes = materialTargetData.numMeshes; - for (let i = 0; i < numMeshes; ++i) { - addMaterialTarget(elDivOptions, i, false); - } - - let materialNames = materialTargetData.materialNames; - let materialNamesAdded = []; - for (let i = 0; i < materialNames.length; ++i) { - let materialName = materialNames[i]; - if (materialNamesAdded.indexOf(materialName) === -1) { - addMaterialTarget(elDivOptions, materialName, true); - materialNamesAdded.push(materialName); - } - } - - materialTargetPropertyUpdate(elDivOptions.propertyValue); -} - -function addMaterialTarget(elDivOptions, targetID, isMaterialName) { - let elementID = elDivOptions.getAttribute("id"); - elementID += isMaterialName ? "-material-" : "-mesh-"; - elementID += targetID; - - let elDiv = document.createElement('div'); - elDiv.className = "materialTargetDiv"; - elDiv.onclick = onToggleMaterialTarget; - elDivOptions.appendChild(elDiv); - - let elInput = document.createElement('input'); - elInput.className = "materialTargetInput"; - elInput.setAttribute("type", "checkbox"); - elInput.setAttribute("id", elementID); - elInput.setAttribute("targetID", targetID); - elInput.setAttribute("isMaterialName", isMaterialName); - elDiv.appendChild(elInput); - - let elLabel = document.createElement('label'); - elLabel.setAttribute("for", elementID); - elLabel.innerText = isMaterialName ? "Material " + targetID : "Mesh Index " + targetID; - elDiv.appendChild(elLabel); - - return elDiv; -} - -function onToggleMaterialTarget(event) { - let elTarget = event.target; - if (elTarget instanceof HTMLInputElement) { - sendMaterialTargetProperty(); - } - event.stopPropagation(); -} - -function setAllMaterialTargetInputs(checked) { - let elDivOptions = getPropertyInputElement("parentMaterialName"); - let elInputs = elDivOptions.getElementsByClassName("materialTargetInput"); - for (let i = 0; i < elInputs.length; ++i) { - elInputs[i].checked = checked; - } -} - -function selectAllMaterialTarget() { - setAllMaterialTargetInputs(true); - sendMaterialTargetProperty(); -} - -function clearAllMaterialTarget() { - setAllMaterialTargetInputs(false); - sendMaterialTargetProperty(); -} - -function sendMaterialTargetProperty() { - let elDivOptions = getPropertyInputElement("parentMaterialName"); - let elInputs = elDivOptions.getElementsByClassName("materialTargetInput"); - - let materialTargetList = []; - for (let i = 0; i < elInputs.length; ++i) { - let elInput = elInputs[i]; - if (elInput.checked) { - let targetID = elInput.getAttribute("targetID"); - if (elInput.getAttribute("isMaterialName") === "true") { - materialTargetList.push(MATERIAL_PREFIX_STRING + targetID); - } else { - materialTargetList.push(targetID); - } - } - } - - let propertyValue = materialTargetList.join(","); - if (propertyValue.length > 1) { - propertyValue = "[" + propertyValue + "]"; - } - - updateProperty("parentMaterialName", propertyValue, false); -} - -function materialTargetPropertyUpdate(propertyValue) { - let elDivOptions = getPropertyInputElement("parentMaterialName"); - let elInputs = elDivOptions.getElementsByClassName("materialTargetInput"); - - if (propertyValue.startsWith('[')) { - propertyValue = propertyValue.substring(1, propertyValue.length); - } - if (propertyValue.endsWith(']')) { - propertyValue = propertyValue.substring(0, propertyValue.length - 1); - } - - let materialTargets = propertyValue.split(","); - for (let i = 0; i < elInputs.length; ++i) { - let elInput = elInputs[i]; - let targetID = elInput.getAttribute("targetID"); - let materialTargetName = targetID; - if (elInput.getAttribute("isMaterialName") === "true") { - materialTargetName = MATERIAL_PREFIX_STRING + targetID; - } - elInput.checked = materialTargets.indexOf(materialTargetName) >= 0; - } - - elDivOptions.propertyValue = propertyValue; -} - -function roundAndFixNumber(number, propertyData) { - let result = number; - if (propertyData.round !== undefined) { - result = Math.round(result * propertyData.round) / propertyData.round; - } - if (propertyData.decimals !== undefined) { - return result.toFixed(propertyData.decimals) - } - return result; -} - -function applyInputNumberPropertyModifiers(number, propertyData) { - const multiplier = propertyData.multiplier !== undefined ? propertyData.multiplier : 1; - return roundAndFixNumber(number / multiplier, propertyData); -} - -function applyOutputNumberPropertyModifiers(number, propertyData) { - const multiplier = propertyData.multiplier !== undefined ? propertyData.multiplier : 1; - return roundAndFixNumber(number * multiplier, propertyData); -} - -const areSetsEqual = (a, b) => a.size === b.size && [...a].every(value => b.has(value)); - - -function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { - const previouslySelectedEntityIDs = selectedEntityIDs; - currentSelections = selections; - selectedEntityIDs = new Set(selections.map(selection => selection.id)); - const multipleSelections = currentSelections.length > 1; - const hasSelectedEntityChanged = !areSetsEqual(selectedEntityIDs, previouslySelectedEntityIDs); - - if (selections.length === 0) { - deleteJSONEditor(); - deleteJSONMaterialEditor(); - - resetProperties(); - showGroupsForType("None"); - - let elIcon = properties.type.elSpan; - elIcon.innerText = NO_SELECTION; - elIcon.style.display = 'inline-block'; - - getPropertyInputElement("userData").value = ""; - showUserDataTextArea(); - showSaveUserDataButton(); - showNewJSONEditorButton(); - - getPropertyInputElement("materialData").value = ""; - showMaterialDataTextArea(); - showSaveMaterialDataButton(); - showNewJSONMaterialEditorButton(); - - disableProperties(); - } else { - if (!isPropertiesToolUpdate && !hasSelectedEntityChanged && document.hasFocus()) { - // in case the selection has not changed and we still have focus on the properties page, - // we will ignore the event. - return; - } - - if (hasSelectedEntityChanged) { - if (!multipleSelections) { - resetServerScriptStatus(); - } - } - - const doSelectElement = !hasSelectedEntityChanged; - - // Get unique entity types, and convert the types Sphere and Box to Shape - const shapeTypes = ["Sphere", "Box"]; - const entityTypes = [...new Set(currentSelections.map(a => - shapeTypes.includes(a.properties.type) ? "Shape" : a.properties.type))]; - - const shownGroups = getGroupsForTypes(entityTypes); - showGroupsForTypes(entityTypes); - - const lockedMultiValue = getMultiplePropertyValue('locked'); - - if (lockedMultiValue.isMultiDiffValue || lockedMultiValue.value) { - disableProperties(); - getPropertyInputElement('locked').removeAttribute('disabled'); - } else { - enableProperties(); - disableSaveUserDataButton(); - disableSaveMaterialDataButton() - } - - const certificateIDMultiValue = getMultiplePropertyValue('certificateID'); - const hasCertifiedInSelection = certificateIDMultiValue.isMultiDiffValue || certificateIDMultiValue.value !== ""; - - Object.entries(properties).forEach(function([propertyID, property]) { - const propertyData = property.data; - const propertyName = property.name; - let propertyMultiValue = getMultiplePropertyValue(propertyName); - let isMultiDiffValue = propertyMultiValue.isMultiDiffValue; - let propertyValue = propertyMultiValue.value; - - if (propertyData.selectionVisibility !== undefined) { - let visibility = propertyData.selectionVisibility; - let propertyVisible = true; - if (!multipleSelections) { - propertyVisible = isFlagSet(visibility, PROPERTY_SELECTION_VISIBILITY.SINGLE_SELECTION); - } else if (isMultiDiffValue) { - propertyVisible = isFlagSet(visibility, PROPERTY_SELECTION_VISIBILITY.MULTI_DIFF_SELECTIONS); - } else { - propertyVisible = isFlagSet(visibility, PROPERTY_SELECTION_VISIBILITY.MULTIPLE_SELECTIONS); - } - setPropertyVisibility(property, propertyVisible); - } - - const isSubProperty = propertyData.subPropertyOf !== undefined; - if (propertyValue === undefined && !isMultiDiffValue && !isSubProperty) { - return; - } - - if (!shownGroups.includes(property.group_id)) { - const WANT_DEBUG_SHOW_HIDDEN_FROM_GROUPS = false; - if (WANT_DEBUG_SHOW_HIDDEN_FROM_GROUPS) { - console.log("Skipping property " + property.data.label + " [" + property.name + - "] from hidden group " + property.group_id); - } - return; - } - - if (propertyData.hideIfCertified && hasCertifiedInSelection) { - propertyValue = "** Certified **"; - property.elInput.disabled = true; - } - - if (propertyName === "type") { - propertyValue = entityTypes.length > 1 ? "Multiple" : propertyMultiValue.values[0]; - } - - switch (propertyData.type) { - case 'string': { - if (isMultiDiffValue) { - if (propertyData.readOnly && propertyData.multiDisplayMode - && propertyData.multiDisplayMode === PROPERTY_MULTI_DISPLAY_MODE.COMMA_SEPARATED_VALUES) { - property.elInput.value = propertyMultiValue.values.join(", "); - } else { - property.elInput.classList.add('multi-diff'); - property.elInput.value = ""; - } - } else { - property.elInput.classList.remove('multi-diff'); - property.elInput.value = propertyValue; - } - break; - } - case 'bool': { - const inverse = propertyData.inverse !== undefined ? propertyData.inverse : false; - if (isSubProperty) { - let subPropertyMultiValue = getMultiplePropertyValue(propertyData.subPropertyOf); - let propertyValue = subPropertyMultiValue.value; - isMultiDiffValue = subPropertyMultiValue.isMultiDiffValue; - if (isMultiDiffValue) { - let detailedSubProperty = getDetailedSubPropertyMPVDiff(subPropertyMultiValue, propertyName); - property.elInput.checked = detailedSubProperty.isChecked; - property.elInput.classList.toggle('multi-diff', detailedSubProperty.isMultiDiff); - } else { - let subProperties = propertyValue.split(","); - let subPropertyValue = subProperties.indexOf(propertyName) > -1; - property.elInput.checked = inverse ? !subPropertyValue : subPropertyValue; - property.elInput.classList.remove('multi-diff'); - } - - } else { - if (isMultiDiffValue) { - property.elInput.checked = false; - } else { - property.elInput.checked = inverse ? !propertyValue : propertyValue; - } - property.elInput.classList.toggle('multi-diff', isMultiDiffValue); - } - - break; - } - case 'number': { - property.elInput.value = isMultiDiffValue ? "" : propertyValue; - property.elInput.classList.toggle('multi-diff', isMultiDiffValue); - break; - } - case 'number-draggable': { - let detailedNumberDiff = getDetailedNumberMPVDiff(propertyMultiValue, propertyData); - property.elNumber.setValue(detailedNumberDiff.averagePerPropertyComponent[0], detailedNumberDiff.propertyComponentDiff[0]); - break; - } - case 'rect': { - let detailedNumberDiff = getDetailedNumberMPVDiff(propertyMultiValue, propertyData); - property.elNumberX.setValue(detailedNumberDiff.averagePerPropertyComponent.x, detailedNumberDiff.propertyComponentDiff.x); - property.elNumberY.setValue(detailedNumberDiff.averagePerPropertyComponent.y, detailedNumberDiff.propertyComponentDiff.y); - property.elNumberWidth.setValue(detailedNumberDiff.averagePerPropertyComponent.width, detailedNumberDiff.propertyComponentDiff.width); - property.elNumberHeight.setValue(detailedNumberDiff.averagePerPropertyComponent.height, detailedNumberDiff.propertyComponentDiff.height); - break; - } - case 'vec3': - case 'vec2': { - let detailedNumberDiff = getDetailedNumberMPVDiff(propertyMultiValue, propertyData); - property.elNumberX.setValue(detailedNumberDiff.averagePerPropertyComponent.x, detailedNumberDiff.propertyComponentDiff.x); - property.elNumberY.setValue(detailedNumberDiff.averagePerPropertyComponent.y, detailedNumberDiff.propertyComponentDiff.y); - if (property.elNumberZ !== undefined) { - property.elNumberZ.setValue(detailedNumberDiff.averagePerPropertyComponent.z, detailedNumberDiff.propertyComponentDiff.z); - } - break; - } - case 'color': { - let displayColor = propertyMultiValue.isMultiDiffValue ? propertyMultiValue.values[0] : propertyValue; - property.elColorPicker.style.backgroundColor = "rgb(" + displayColor.red + "," + - displayColor.green + "," + - displayColor.blue + ")"; - property.elColorPicker.classList.toggle('multi-diff', propertyMultiValue.isMultiDiffValue); - - if (hasSelectedEntityChanged && $(property.elColorPicker).attr('active') === 'true') { - // Set the color picker inactive before setting the color, - // otherwise an update will be sent directly after setting it here. - $(property.elColorPicker).attr('active', 'false'); - colorPickers['#' + property.elementID].colpickSetColor({ - "r": displayColor.red, - "g": displayColor.green, - "b": displayColor.blue - }); - $(property.elColorPicker).attr('active', 'true'); - } - - property.elNumberR.setValue(displayColor.red); - property.elNumberG.setValue(displayColor.green); - property.elNumberB.setValue(displayColor.blue); - break; - } - case 'dropdown': { - property.elInput.classList.toggle('multi-diff', isMultiDiffValue); - property.elInput.value = isMultiDiffValue ? "" : propertyValue; - setDropdownText(property.elInput); - break; - } - case 'textarea': { - property.elInput.value = propertyValue; - setTextareaScrolling(property.elInput); - break; - } - case 'icon': { - property.elSpan.innerHTML = propertyData.icons[propertyValue]; - property.elSpan.style.display = "inline-block"; - break; - } - case 'texture': { - property.elInput.value = isMultiDiffValue ? "" : propertyValue; - property.elInput.classList.toggle('multi-diff', isMultiDiffValue); - if (isMultiDiffValue) { - property.elInput.setMultipleValues(); - } else { - property.elInput.imageLoad(property.elInput.value); - } - break; - } - case 'dynamic-multiselect': { - if (!isMultiDiffValue && property.data.propertyUpdate) { - property.data.propertyUpdate(propertyValue); - } - break; - } - } - - let showPropertyRules = property.showPropertyRules; - if (showPropertyRules !== undefined) { - for (let propertyToShow in showPropertyRules) { - let showIfThisPropertyValue = showPropertyRules[propertyToShow]; - let show = String(propertyValue) === String(showIfThisPropertyValue); - showPropertyElement(propertyToShow, show); - } - } - }); - - updateVisibleSpaceModeProperties(); - - let userDataMultiValue = getMultiplePropertyValue("userData"); - let userDataTextArea = getPropertyInputElement("userData"); - let json = null; - if (!userDataMultiValue.isMultiDiffValue) { - try { - json = JSON.parse(userDataMultiValue.value); - } catch (e) { - - } - } - if (json !== null) { - if (editor === null) { - createJSONEditor(); - } - userDataTextArea.classList.remove('multi-diff'); - setEditorJSON(json); - showSaveUserDataButton(); - hideUserDataTextArea(); - hideNewJSONEditorButton(); - hideUserDataSaved(); - } else { - // normal text - deleteJSONEditor(); - userDataTextArea.classList.toggle('multi-diff', userDataMultiValue.isMultiDiffValue); - userDataTextArea.value = userDataMultiValue.isMultiDiffValue ? "" : userDataMultiValue.value; - - showUserDataTextArea(); - showNewJSONEditorButton(); - hideSaveUserDataButton(); - hideUserDataSaved(); - } - - let materialDataMultiValue = getMultiplePropertyValue("materialData"); - let materialDataTextArea = getPropertyInputElement("materialData"); - let materialJson = null; - if (!materialDataMultiValue.isMultiDiffValue) { - try { - materialJson = JSON.parse(materialDataMultiValue.value); - } catch (e) { - - } - } - if (materialJson !== null) { - if (materialEditor === null) { - createJSONMaterialEditor(); - } - materialDataTextArea.classList.remove('multi-diff'); - setMaterialEditorJSON(materialJson); - showSaveMaterialDataButton(); - hideMaterialDataTextArea(); - hideNewJSONMaterialEditorButton(); - hideMaterialDataSaved(); - } else { - // normal text - deleteJSONMaterialEditor(); - materialDataTextArea.classList.toggle('multi-diff', materialDataMultiValue.isMultiDiffValue); - materialDataTextArea.value = materialDataMultiValue.isMultiDiffValue ? "" : materialDataMultiValue.value; - showMaterialDataTextArea(); - showNewJSONMaterialEditorButton(); - hideSaveMaterialDataButton(); - hideMaterialDataSaved(); - } - - if (hasSelectedEntityChanged && selections.length === 1 && entityTypes[0] === "Material") { - requestMaterialTarget(); - } - - let activeElement = document.activeElement; - if (doSelectElement && typeof activeElement.select !== "undefined") { - activeElement.select(); - } - } -} - -function loaded() { - openEventBridge(function() { - let elPropertiesList = document.getElementById("properties-list"); - - GROUPS.forEach(function(group) { - let elGroup; - if (group.addToGroup !== undefined) { - let fieldset = document.getElementById("properties-" + group.addToGroup); - elGroup = document.createElement('div'); - fieldset.appendChild(elGroup); - } else { - elGroup = document.createElement('div'); - elGroup.className = 'section ' + (group.isMinor ? "minor" : "major"); - elGroup.setAttribute("id", "properties-" + group.id); - elPropertiesList.appendChild(elGroup); - } - - if (group.label !== undefined) { - let elLegend = document.createElement('div'); - elLegend.className = "section-header"; - - elLegend.appendChild(createElementFromHTML(`
${group.label}
`)); - - let elSpan = document.createElement('span'); - elSpan.className = "collapse-icon"; - elSpan.innerText = "M"; - elLegend.appendChild(elSpan); - elGroup.appendChild(elLegend); - } - - group.properties.forEach(function(propertyData) { - let propertyType = propertyData.type; - let propertyID = propertyData.propertyID; - let propertyName = propertyData.propertyName !== undefined ? propertyData.propertyName : propertyID; - let propertySpaceMode = propertyData.spaceMode !== undefined ? propertyData.spaceMode : PROPERTY_SPACE_MODE.ALL; - let propertyElementID = "property-" + propertyID; - propertyElementID = propertyElementID.replace('.', '-'); - - let elContainer, elLabel; - - if (propertyData.replaceID === undefined) { - // Create subheader, or create new property and append it. - if (propertyType === "sub-header") { - elContainer = createElementFromHTML( - `
${propertyData.label}
`); - } else { - elContainer = document.createElement('div'); - elContainer.setAttribute("id", "div-" + propertyElementID); - elContainer.className = 'property container'; - } - - if (group.twoColumn && propertyData.column !== undefined && propertyData.column !== -1) { - let columnName = group.id + "column" + propertyData.column; - let elColumn = document.getElementById(columnName); - if (!elColumn) { - let columnDivName = group.id + "columnDiv"; - let elColumnDiv = document.getElementById(columnDivName); - if (!elColumnDiv) { - elColumnDiv = document.createElement('div'); - elColumnDiv.className = "two-column"; - elColumnDiv.setAttribute("id", group.id + "columnDiv"); - elGroup.appendChild(elColumnDiv); - } - elColumn = document.createElement('fieldset'); - elColumn.className = "column"; - elColumn.setAttribute("id", columnName); - elColumnDiv.appendChild(elColumn); - } - elColumn.appendChild(elContainer); - } else { - elGroup.appendChild(elContainer); - } - - let labelText = propertyData.label !== undefined ? propertyData.label : ""; - let className = ''; - if (propertyData.indentedLabel || propertyData.showPropertyRule !== undefined) { - className = 'indented'; - } - elLabel = createElementFromHTML( - ``); - elContainer.appendChild(elLabel); - } else { - elContainer = document.getElementById(propertyData.replaceID); - } - - if (elLabel) { - createAppTooltip.registerTooltipElement(elLabel.childNodes[0], propertyID, propertyName); - } - - let elProperty = createElementFromHTML('
'); - elContainer.appendChild(elProperty); - - if (propertyType === 'triple') { - elProperty.className = 'flex-row'; - for (let i = 0; i < propertyData.properties.length; ++i) { - let innerPropertyData = propertyData.properties[i]; - - let elWrapper = createElementFromHTML('
'); - elProperty.appendChild(elWrapper); - - let propertyID = innerPropertyData.propertyID; - let propertyName = innerPropertyData.propertyName !== undefined ? innerPropertyData.propertyName : propertyID; - let propertyElementID = "property-" + propertyID; - propertyElementID = propertyElementID.replace('.', '-'); - - let property = createProperty(innerPropertyData, propertyElementID, propertyName, propertyID, elWrapper); - property.isParticleProperty = group.id.includes("particles"); - property.elContainer = elContainer; - property.spaceMode = propertySpaceMode; - property.group_id = group.id; - - let elLabel = createElementFromHTML(`
${innerPropertyData.label}
`); - createAppTooltip.registerTooltipElement(elLabel, propertyID, propertyName); - - elWrapper.appendChild(elLabel); - - if (property.type !== 'placeholder') { - properties[propertyID] = property; - } - if (innerPropertyData.type === 'number' || innerPropertyData.type === 'number-draggable') { - propertyRangeRequests.push(propertyID); - } - } - } else { - let property = createProperty(propertyData, propertyElementID, propertyName, propertyID, elProperty); - property.isParticleProperty = group.id.includes("particles"); - property.elContainer = elContainer; - property.spaceMode = propertySpaceMode; - property.group_id = group.id; - - if (property.type !== 'placeholder') { - properties[propertyID] = property; - } - if (propertyData.type === 'number' || propertyData.type === 'number-draggable' || - propertyData.type === 'vec2' || propertyData.type === 'vec3' || propertyData.type === 'rect') { - propertyRangeRequests.push(propertyID); - } - - let showPropertyRule = propertyData.showPropertyRule; - if (showPropertyRule !== undefined) { - let dependentProperty = Object.keys(showPropertyRule)[0]; - let dependentPropertyValue = showPropertyRule[dependentProperty]; - if (properties[dependentProperty] === undefined) { - properties[dependentProperty] = {}; - } - if (properties[dependentProperty].showPropertyRules === undefined) { - properties[dependentProperty].showPropertyRules = {}; - } - properties[dependentProperty].showPropertyRules[propertyID] = dependentPropertyValue; - } - } - }); - - elGroups[group.id] = elGroup; - }); - - let minorSections = document.querySelectorAll(".section.minor"); - minorSections[minorSections.length - 1].className += " last"; - - updateVisibleSpaceModeProperties(); - - if (window.EventBridge !== undefined) { - EventBridge.scriptEventReceived.connect(function(data) { - data = JSON.parse(data); - if (data.type === "server_script_status" && selectedEntityIDs.size === 1) { - let elServerScriptError = document.getElementById("property-serverScripts-error"); - let elServerScriptStatus = document.getElementById("property-serverScripts-status"); - elServerScriptError.value = data.errorInfo; - // If we just set elServerScriptError's display to block or none, we still end up with - // it's parent contributing 21px bottom padding even when elServerScriptError is display:none. - // So set it's parent to block or none - elServerScriptError.parentElement.style.display = data.errorInfo ? "block" : "none"; - if (data.statusRetrieved === false) { - elServerScriptStatus.innerText = "Failed to retrieve status"; - } else if (data.isRunning) { - elServerScriptStatus.innerText = ENTITY_SCRIPT_STATUS[data.status] || data.status; - } else { - elServerScriptStatus.innerText = NOT_RUNNING_SCRIPT_STATUS; - } - } else if (data.type === "update" && data.selections) { - if (data.spaceMode !== undefined) { - currentSpaceMode = data.spaceMode === "local" ? PROPERTY_SPACE_MODE.LOCAL : PROPERTY_SPACE_MODE.WORLD; - } - handleEntitySelectionUpdate(data.selections, data.isPropertiesToolUpdate); - } else if (data.type === 'tooltipsReply') { - createAppTooltip.setIsEnabled(!data.hmdActive); - createAppTooltip.setTooltipData(data.tooltips); - } else if (data.type === 'hmdActiveChanged') { - createAppTooltip.setIsEnabled(!data.hmdActive); - } else if (data.type === 'setSpaceMode') { - currentSpaceMode = data.spaceMode === "local" ? PROPERTY_SPACE_MODE.LOCAL : PROPERTY_SPACE_MODE.WORLD; - updateVisibleSpaceModeProperties(); - } else if (data.type === 'propertyRangeReply') { - let propertyRanges = data.propertyRanges; - for (let property in propertyRanges) { - let propertyRange = propertyRanges[property]; - if (propertyRange !== undefined) { - let propertyData = properties[property].data; - let multiplier = propertyData.multiplier; - if (propertyData.min === undefined && propertyRange.minimum !== "") { - propertyData.min = propertyRange.minimum; - if (multiplier !== undefined) { - propertyData.min /= multiplier; - } - } - if (propertyData.max === undefined && propertyRange.maximum !== "") { - propertyData.max = propertyRange.maximum; - if (multiplier !== undefined) { - propertyData.max /= multiplier; - } - } - switch (propertyData.type) { - case 'number': - updateNumberMinMax(properties[property]); - break; - case 'number-draggable': - updateNumberDraggableMinMax(properties[property]); - break; - case 'vec3': - case 'vec2': - updateVectorMinMax(properties[property]); - break; - case 'rect': - updateRectMinMax(properties[property]); - break; - } - } - } - } else if (data.type === 'materialTargetReply') { - if (data.entityID === getFirstSelectedID()) { - setMaterialTargetData(data.materialTargetData); - } - } - }); - - // Request tooltips and property ranges as soon as we can process a reply: - EventBridge.emitWebEvent(JSON.stringify({ type: 'tooltipsRequest' })); - EventBridge.emitWebEvent(JSON.stringify({ type: 'propertyRangeRequest', properties: propertyRangeRequests })); - } - - // Server Script Status - let elServerScriptStatusOuter = document.getElementById('div-property-serverScriptStatus'); - let elServerScriptStatusContainer = document.getElementById('div-property-serverScriptStatus').childNodes[1]; - let serverScriptStatusElementID = 'property-serverScripts-status'; - createAppTooltip.registerTooltipElement(elServerScriptStatusOuter.childNodes[0], "serverScriptsStatus"); - let elServerScriptStatus = document.createElement('div'); - elServerScriptStatus.setAttribute("id", serverScriptStatusElementID); - elServerScriptStatusContainer.appendChild(elServerScriptStatus); - - // Server Script Error - let elServerScripts = getPropertyInputElement("serverScripts"); - let elDiv = document.createElement('div'); - elDiv.className = "property"; - let elServerScriptError = document.createElement('textarea'); - let serverScriptErrorElementID = 'property-serverScripts-error'; - elServerScriptError.setAttribute("id", serverScriptErrorElementID); - elDiv.appendChild(elServerScriptError); - elServerScriptStatusContainer.appendChild(elDiv); - - let elScript = getPropertyInputElement("script"); - elScript.parentNode.className = "url refresh"; - elServerScripts.parentNode.className = "url refresh"; - - // User Data - let userDataProperty = properties["userData"]; - let elUserData = userDataProperty.elInput; - let userDataElementID = userDataProperty.elementID; - elDiv = elUserData.parentNode; - let elStaticUserData = document.createElement('div'); - elStaticUserData.setAttribute("id", userDataElementID + "-static"); - let elUserDataEditor = document.createElement('div'); - elUserDataEditor.setAttribute("id", userDataElementID + "-editor"); - let elUserDataEditorStatus = document.createElement('div'); - elUserDataEditorStatus.setAttribute("id", userDataElementID + "-editorStatus"); - let elUserDataSaved = document.createElement('span'); - elUserDataSaved.setAttribute("id", userDataElementID + "-saved"); - elUserDataSaved.innerText = "Saved!"; - elDiv.childNodes[JSON_EDITOR_ROW_DIV_INDEX].appendChild(elUserDataSaved); - elDiv.insertBefore(elStaticUserData, elUserData); - elDiv.insertBefore(elUserDataEditor, elUserData); - elDiv.insertBefore(elUserDataEditorStatus, elUserData); - - // Material Data - let materialDataProperty = properties["materialData"]; - let elMaterialData = materialDataProperty.elInput; - let materialDataElementID = materialDataProperty.elementID; - elDiv = elMaterialData.parentNode; - let elStaticMaterialData = document.createElement('div'); - elStaticMaterialData.setAttribute("id", materialDataElementID + "-static"); - let elMaterialDataEditor = document.createElement('div'); - elMaterialDataEditor.setAttribute("id", materialDataElementID + "-editor"); - let elMaterialDataEditorStatus = document.createElement('div'); - elMaterialDataEditorStatus.setAttribute("id", materialDataElementID + "-editorStatus"); - let elMaterialDataSaved = document.createElement('span'); - elMaterialDataSaved.setAttribute("id", materialDataElementID + "-saved"); - elMaterialDataSaved.innerText = "Saved!"; - elDiv.childNodes[JSON_EDITOR_ROW_DIV_INDEX].appendChild(elMaterialDataSaved); - elDiv.insertBefore(elStaticMaterialData, elMaterialData); - elDiv.insertBefore(elMaterialDataEditor, elMaterialData); - elDiv.insertBefore(elMaterialDataEditorStatus, elMaterialData); - - // Collapsible sections - let elCollapsible = document.getElementsByClassName("collapse-icon"); - - let toggleCollapsedEvent = function(event) { - let element = this.parentNode.parentNode; - let isCollapsed = element.dataset.collapsed !== "true"; - element.dataset.collapsed = isCollapsed ? "true" : false; - element.setAttribute("collapsed", isCollapsed ? "true" : "false"); - this.textContent = isCollapsed ? "L" : "M"; - }; - - for (let collapseIndex = 0, numCollapsibles = elCollapsible.length; collapseIndex < numCollapsibles; ++collapseIndex) { - let curCollapsibleElement = elCollapsible[collapseIndex]; - curCollapsibleElement.addEventListener("click", toggleCollapsedEvent, true); - } - - // Textarea scrollbars - let elTextareas = document.getElementsByTagName("TEXTAREA"); - - let textareaOnChangeEvent = function(event) { - setTextareaScrolling(event.target); - }; - - for (let textAreaIndex = 0, numTextAreas = elTextareas.length; textAreaIndex < numTextAreas; ++textAreaIndex) { - let curTextAreaElement = elTextareas[textAreaIndex]; - setTextareaScrolling(curTextAreaElement); - curTextAreaElement.addEventListener("input", textareaOnChangeEvent, false); - curTextAreaElement.addEventListener("change", textareaOnChangeEvent, false); - /* FIXME: Detect and update textarea scrolling attribute on resize. Unfortunately textarea doesn't have a resize - event; mouseup is a partial stand-in but doesn't handle resizing if mouse moves outside textarea rectangle. */ - curTextAreaElement.addEventListener("mouseup", textareaOnChangeEvent, false); - } - - // Dropdowns - // For each dropdown the following replacement is created in place of the original dropdown... - // Structure created: - //
- //
display textcarat
- //
- //
    - //
  • 0) { - let el = elDropdowns[0]; - el.parentNode.removeChild(el); - elDropdowns = document.getElementsByTagName("select"); - } - - const KEY_CODES = { - BACKSPACE: 8, - DELETE: 46 - }; - - document.addEventListener("keyup", function (keyUpEvent) { - const FILTERED_NODE_NAMES = ["INPUT", "TEXTAREA"]; - if (FILTERED_NODE_NAMES.includes(keyUpEvent.target.nodeName)) { - return; - } - - if (elUserDataEditor.contains(keyUpEvent.target) || elMaterialDataEditor.contains(keyUpEvent.target)) { - return; - } - - let {code, key, keyCode, altKey, ctrlKey, metaKey, shiftKey} = keyUpEvent; - - let controlKey = window.navigator.platform.startsWith("Mac") ? metaKey : ctrlKey; - - let keyCodeString; - switch (keyCode) { - case KEY_CODES.DELETE: - keyCodeString = "Delete"; - break; - case KEY_CODES.BACKSPACE: - keyCodeString = "Backspace"; - break; - default: - keyCodeString = String.fromCharCode(keyUpEvent.keyCode); - break; - } - - EventBridge.emitWebEvent(JSON.stringify({ - type: 'keyUpEvent', - keyUpEvent: { - code, - key, - keyCode, - keyCodeString, - altKey, - controlKey, - shiftKey, - } - })); - }, false); - - window.onblur = function() { - // Fake a change event - let ev = document.createEvent("HTMLEvents"); - ev.initEvent("change", true, true); - document.activeElement.dispatchEvent(ev); - }; - - // For input and textarea elements, select all of the text on focus - let els = document.querySelectorAll("input, textarea"); - for (let i = 0; i < els.length; ++i) { - els[i].onfocus = function (e) { - e.target.select(); - }; - } - - bindAllNonJSONEditorElements(); - - showGroupsForType("None"); - resetProperties(); - disableProperties(); - }); - - augmentSpinButtons(); - disableDragDrop(); - - // Disable right-click context menu which is not visible in the HMD and makes it seem like the app has locked - document.addEventListener("contextmenu", function(event) { - event.preventDefault(); - }, false); - - setTimeout(function() { - EventBridge.emitWebEvent(JSON.stringify({ type: 'propertiesPageReady' })); - }, 1000); -} diff --git a/scripts/simplifiedUI/system/html/js/eventBridgeLoader.js b/scripts/simplifiedUI/system/html/js/eventBridgeLoader.js deleted file mode 100644 index 411780853b..0000000000 --- a/scripts/simplifiedUI/system/html/js/eventBridgeLoader.js +++ /dev/null @@ -1,19 +0,0 @@ - -//public slots: -// void emitWebEvent(const QString& data); -// void emitScriptEvent(const QString& data); -// -//signals: -// void webEventReceived(const QString& data); -// void scriptEventReceived(const QString& data); -// - -var EventBridge; -var WebChannel; - -openEventBridge = function(callback) { - WebChannel = new QWebChannel(qt.webChannelTransport, function (channel) { - EventBridge = WebChannel.objects.eventBridge; - callback(EventBridge); - }); -} diff --git a/scripts/simplifiedUI/system/html/js/gridControls.js b/scripts/simplifiedUI/system/html/js/gridControls.js deleted file mode 100644 index e27dac522b..0000000000 --- a/scripts/simplifiedUI/system/html/js/gridControls.js +++ /dev/null @@ -1,161 +0,0 @@ -// gridControls.js -// -// Created by Ryan Huffman on 6 Nov 2014 -// Copyright 2014 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 - -function loaded() { - openEventBridge(function() { - elPosY = document.getElementById("horiz-y"); - elMinorSpacing = document.getElementById("minor-spacing"); - elMajorSpacing = document.getElementById("major-spacing"); - elSnapToGrid = document.getElementById("snap-to-grid"); - elHorizontalGridVisible = document.getElementById("horiz-grid-visible"); - elMoveToSelection = document.getElementById("move-to-selection"); - elMoveToAvatar = document.getElementById("move-to-avatar"); - - if (window.EventBridge !== undefined) { - EventBridge.scriptEventReceived.connect(function(data) { - data = JSON.parse(data); - - if (data.origin) { - var origin = data.origin; - elPosY.value = origin.y; - } - - if (data.minorGridEvery !== undefined) { - elMinorSpacing.value = data.minorGridEvery; - } - - if (data.majorGridEvery !== undefined) { - elMajorSpacing.value = data.majorGridEvery; - } - - if (data.gridColor) { - gridColor = data.gridColor; - } - - if (data.snapToGrid !== undefined) { - elSnapToGrid.checked = data.snapToGrid == true; - } - - if (data.visible !== undefined) { - elHorizontalGridVisible.checked = data.visible == true; - } - }); - - function emitUpdate() { - EventBridge.emitWebEvent(JSON.stringify({ - type: "update", - origin: { - y: elPosY.value, - }, - minorGridEvery: elMinorSpacing.value, - majorGridEvery: elMajorSpacing.value, - gridColor: gridColor, - snapToGrid: elSnapToGrid.checked, - visible: elHorizontalGridVisible.checked, - })); - } - - } - - elPosY.addEventListener("change", emitUpdate); - elMinorSpacing.addEventListener("change", emitUpdate); - elMajorSpacing.addEventListener("change", emitUpdate); - elSnapToGrid.addEventListener("change", emitUpdate); - elHorizontalGridVisible.addEventListener("change", emitUpdate); - - elMoveToAvatar.addEventListener("click", function() { - EventBridge.emitWebEvent(JSON.stringify({ - type: "action", - action: "moveToAvatar", - })); - }); - elMoveToSelection.addEventListener("click", function() { - EventBridge.emitWebEvent(JSON.stringify({ - type: "action", - action: "moveToSelection", - })); - }); - - var gridColor = { red: 255, green: 255, blue: 255 }; - var elColor = document.getElementById("grid-color"); - elColor.style.backgroundColor = "rgb(" + gridColor.red + "," + gridColor.green + "," + gridColor.blue + ")"; - - var colorPickFunction = function (red, green, blue) { - gridColor = { red: red, green: green, blue: blue }; - emitUpdate(); - }; - - $('#grid-color').colpick({ - colorScheme: 'dark', - layout: 'rgbhex', - color: { r: gridColor.red, g: gridColor.green, b: gridColor.blue }, - submit: false, - onShow: function (colpick) { - $('#grid-color').attr('active', 'true'); - }, - onHide: function (colpick) { - $('#grid-color').attr('active', 'false'); - }, - onChange: function (hsb, hex, rgb, el) { - $(el).css('background-color', '#' + hex); - colorPickFunction(rgb.r, rgb.g, rgb.b); - } - }); - - augmentSpinButtons(); - disableDragDrop(); - - EventBridge.emitWebEvent(JSON.stringify({ type: 'init' })); - }); - - const KEY_CODES = { - BACKSPACE: 8, - DELETE: 46 - }; - - document.addEventListener("keyup", function (keyUpEvent) { - const FILTERED_NODE_NAMES = ["INPUT", "TEXTAREA"]; - if (FILTERED_NODE_NAMES.includes(keyUpEvent.target.nodeName)) { - return; - } - let {code, key, keyCode, altKey, ctrlKey, metaKey, shiftKey} = keyUpEvent; - - let controlKey = window.navigator.platform.startsWith("Mac") ? metaKey : ctrlKey; - - let keyCodeString; - switch (keyCode) { - case KEY_CODES.DELETE: - keyCodeString = "Delete"; - break; - case KEY_CODES.BACKSPACE: - keyCodeString = "Backspace"; - break; - default: - keyCodeString = String.fromCharCode(keyUpEvent.keyCode); - break; - } - - EventBridge.emitWebEvent(JSON.stringify({ - type: 'keyUpEvent', - keyUpEvent: { - code, - key, - keyCode, - keyCodeString, - altKey, - controlKey, - shiftKey, - } - })); - }, false); - - // Disable right-click context menu which is not visible in the HMD and makes it seem like the app has locked - document.addEventListener("contextmenu", function (event) { - event.preventDefault(); - }, false); -} diff --git a/scripts/simplifiedUI/system/html/js/includes.js b/scripts/simplifiedUI/system/html/js/includes.js deleted file mode 100644 index c604115f91..0000000000 --- a/scripts/simplifiedUI/system/html/js/includes.js +++ /dev/null @@ -1,27 +0,0 @@ -// -// includes.js -// -// Created by David Back on 3 Jan 2019 -// Copyright 2016 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 -// - -const ENTITY_TYPE_ICON = { - Box: "m", - Grid: "", - Image: "", - Light: "p", - Material: "", - Model: "", - ParticleEffect: "", - PolyVox: "", - PolyLine: "", - Shape: "n", - Sphere: "n", - Text: "l", - Web: "q", - Zone: "o", - Multiple: "", -}; diff --git a/scripts/simplifiedUI/system/html/js/jquery-2.1.4.min.js b/scripts/simplifiedUI/system/html/js/jquery-2.1.4.min.js deleted file mode 100644 index 49990d6e14..0000000000 --- a/scripts/simplifiedUI/system/html/js/jquery-2.1.4.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! jQuery v2.1.4 | (c) 2005, 2015 jQuery Foundation, Inc. | jquery.org/license */ -!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l=a.document,m="2.1.4",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return!n.isArray(a)&&a-parseFloat(a)+1>=0},isPlainObject:function(a){return"object"!==n.type(a)||a.nodeType||n.isWindow(a)?!1:a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf")?!1:!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=l.createElement("script"),b.text=a,l.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:k}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b="length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,aa=/[+~]/,ba=/'|\\/g,ca=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),da=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ea=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fa){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(ba,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+ra(o[l]);w=aa.test(a)&&pa(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",ea,!1):e.attachEvent&&e.attachEvent("onunload",ea)),p=!f(g),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?la(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ca,da),a[3]=(a[3]||a[4]||a[5]||"").replace(ca,da),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ca,da).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(ca,da),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return W.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(ca,da).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:oa(function(){return[0]}),last:oa(function(a,b){return[b-1]}),eq:oa(function(a,b,c){return[0>c?c+b:c]}),even:oa(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:oa(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:oa(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:oa(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function sa(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function ta(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ua(a,b,c){for(var d=0,e=b.length;e>d;d++)ga(a,b[d],c);return c}function va(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wa(a,b,c,d,e,f){return d&&!d[u]&&(d=wa(d)),e&&!e[u]&&(e=wa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ua(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:va(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=va(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=va(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sa(function(a){return a===b},h,!0),l=sa(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sa(ta(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wa(i>1&&ta(m),i>1&&ra(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xa(a.slice(i,e)),f>e&&xa(a=a.slice(e)),f>e&&ra(a))}m.push(c)}return ta(m)}function ya(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=va(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&ga.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,ya(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ca,da),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ca,da),aa.test(j[0].type)&&pa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&ra(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,aa.test(a)&&pa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return g.call(b,a)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:l,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=l.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=l,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};A.prototype=n.fn,y=n(l);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?g.call(n(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(C[a]||n.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return n.each(a.match(E)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&n.each(arguments,function(a,b){var c;while((c=n.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(H.resolveWith(l,[n]),n.fn.triggerHandler&&(n(l).triggerHandler("ready"),n(l).off("ready"))))}});function I(){l.removeEventListener("DOMContentLoaded",I,!1),a.removeEventListener("load",I,!1),n.ready()}n.ready.promise=function(b){return H||(H=n.Deferred(),"complete"===l.readyState?setTimeout(n.ready):(l.addEventListener("DOMContentLoaded",I,!1),a.addEventListener("load",I,!1))),H.promise(b)},n.ready.promise();var J=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f};n.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=n.expando+K.uid++}K.uid=1,K.accepts=n.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,n.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if("string"==typeof b)f[b]=c;else if(n.isEmptyObject(f))n.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!n.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(O,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){ -return M.access(a,b,c)},removeData:function(a,b){M.remove(a,b)},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=M.get(f),1===f.nodeType&&!L.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));L.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=n.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf("-")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=L.get(a,b),c&&(!d||n.isArray(c)?d=L.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return L.get(a,c)||L.access(a,c,{empty:n.Callbacks("once memory").add(function(){L.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthx",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";k.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|pointer|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return l.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof n!==U&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,m,o,p=[d||l],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||l,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+n.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},e||!o.trigger||o.trigger.apply(d,c)!==!1)){if(!e&&!o.noBubble&&!n.isWindow(d)){for(i=o.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||l)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:o.bindType||q,m=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),m&&m.apply(g,c),m=k&&g[k],m&&m.apply&&n.acceptData(g)&&(b.result=m.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!n.acceptData(d)||k&&n.isFunction(d[q])&&!n.isWindow(d)&&(h=d[k],h&&(d[k]=null),n.event.triggered=q,d[q](),n.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>=0:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\/>/gi,ba=/<([\w:]+)/,ca=/<|&#?\w+;/,da=/<(?:script|style|link)/i,ea=/checked\s*(?:[^=]|=\s*.checked.)/i,fa=/^$|\/(?:java|ecma)script/i,ga=/^true\/(.*)/,ha=/^\s*\s*$/g,ia={option:[1,""],thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};ia.optgroup=ia.option,ia.tbody=ia.tfoot=ia.colgroup=ia.caption=ia.thead,ia.th=ia.td;function ja(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function ka(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function la(a){var b=ga.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function ma(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function na(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=n.extend({},h),M.set(b,i))}}function oa(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function pa(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}n.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=oa(h),f=oa(a),d=0,e=f.length;e>d;d++)pa(f[d],g[d]);if(b)if(c)for(f=f||oa(a),g=g||oa(h),d=0,e=f.length;e>d;d++)na(f[d],g[d]);else na(a,h);return g=oa(h,"script"),g.length>0&&ma(g,!i&&oa(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,o=a.length;o>m;m++)if(e=a[m],e||0===e)if("object"===n.type(e))n.merge(l,e.nodeType?[e]:e);else if(ca.test(e)){f=f||k.appendChild(b.createElement("div")),g=(ba.exec(e)||["",""])[1].toLowerCase(),h=ia[g]||ia._default,f.innerHTML=h[1]+e.replace(aa,"<$1>")+h[2],j=h[0];while(j--)f=f.lastChild;n.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===n.inArray(e,d))&&(i=n.contains(e.ownerDocument,e),f=oa(k.appendChild(e),"script"),i&&ma(f),c)){j=0;while(e=f[j++])fa.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f=n.event.special,g=0;void 0!==(c=a[g]);g++){if(n.acceptData(c)&&(e=c[L.expando],e&&(b=L.cache[e]))){if(b.events)for(d in b.events)f[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);L.cache[e]&&delete L.cache[e]}delete M.cache[c[M.expando]]}}}),n.fn.extend({text:function(a){return J(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=ja(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=ja(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(oa(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&ma(oa(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(oa(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!da.test(a)&&!ia[(ba.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(aa,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(oa(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(oa(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,m=this,o=l-1,p=a[0],q=n.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&ea.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(c=n.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=n.map(oa(c,"script"),ka),g=f.length;l>j;j++)h=c,j!==o&&(h=n.clone(h,!0,!0),g&&n.merge(f,oa(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,n.map(f,la),j=0;g>j;j++)h=f[j],fa.test(h.type||"")&&!L.access(h,"globalEval")&&n.contains(i,h)&&(h.src?n._evalUrl&&n._evalUrl(h.src):n.globalEval(h.textContent.replace(ha,"")))}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),n(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qa,ra={};function sa(b,c){var d,e=n(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:n.css(e[0],"display");return e.detach(),f}function ta(a){var b=l,c=ra[a];return c||(c=sa(a,b),"none"!==c&&c||(qa=(qa||n("