mirror of
https://github.com/lubosz/overte.git
synced 2025-04-19 17:03:43 +02:00
Merge branch 'master' into bugz-690
This commit is contained in:
commit
386d945eeb
45 changed files with 1685 additions and 492 deletions
|
@ -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
|
||||
|
|
|
@ -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,13 @@ 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})
|
||||
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 +282,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 +296,75 @@ 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 "${SRC_FOLDER}/${VERTEX_NAME}.slv")
|
||||
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 "${SRC_FOLDER}/${FRAGMENT_NAME}.slf")
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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: "<b>Audio Input:</b> " + 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: "<b>Audio Output:</b> " + 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);
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
//
|
||||
#include "PerformanceManager.h"
|
||||
|
||||
#include <platform/Platform.h>
|
||||
#include <platform/PlatformKeys.h>
|
||||
#include <platform/Profiler.h>
|
||||
|
||||
#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<LODManager>()->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<LODManager>()->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<LODManager>()->setWorldDetailQuality(0.75f);
|
||||
|
||||
break;
|
||||
|
|
|
@ -19,6 +19,11 @@
|
|||
|
||||
const int SafeLanding::SEQUENCE_MODULO = std::numeric_limits<OCTREE_PACKET_SEQUENCE>::max() + 1;
|
||||
|
||||
CalculateEntityLoadingPriority SafeLanding::entityLoadingOperatorElevateCollidables = [](const EntityItem& entityItem) {
|
||||
const int COLLIDABLE_ENTITY_PRIORITY = 10.0f;
|
||||
return entityItem.getCollisionless() * COLLIDABLE_ENTITY_PRIORITY;
|
||||
};
|
||||
|
||||
namespace {
|
||||
template<typename T> bool lessThanWraparound(int a, int b) {
|
||||
constexpr int MAX_T_VALUE = std::numeric_limits<T>::max();
|
||||
|
@ -52,7 +57,8 @@ void SafeLanding::startTracking(QSharedPointer<EntityTreeRenderer> entityTreeRen
|
|||
connect(std::const_pointer_cast<EntityTree>(entityTree).get(),
|
||||
&EntityTree::deletingEntity, this, &SafeLanding::deleteTrackedEntity);
|
||||
|
||||
EntityTreeRenderer::setEntityLoadingPriorityFunction(&ElevatedPriority);
|
||||
_prevEntityLoadingPriorityOperator = EntityTreeRenderer::getEntityLoadingPriorityOperator();
|
||||
EntityTreeRenderer::setEntityLoadingPriorityFunction(entityLoadingOperatorElevateCollidables);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -162,7 +168,7 @@ void SafeLanding::stopTracking() {
|
|||
&EntityTree::deletingEntity, this, &SafeLanding::deleteTrackedEntity);
|
||||
_entityTreeRenderer.reset();
|
||||
}
|
||||
EntityTreeRenderer::setEntityLoadingPriorityFunction(StandardPriority);
|
||||
EntityTreeRenderer::setEntityLoadingPriorityFunction(_prevEntityLoadingPriorityOperator);
|
||||
}
|
||||
|
||||
bool SafeLanding::trackingIsComplete() const {
|
||||
|
@ -205,10 +211,6 @@ bool SafeLanding::isEntityPhysicsReady(const EntityItemPointer& entity) {
|
|||
return true;
|
||||
}
|
||||
|
||||
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();
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#include "EntityItem.h"
|
||||
#include "EntityDynamicInterface.h"
|
||||
|
||||
#include "EntityTreeRenderer.h"
|
||||
|
||||
class EntityTreeRenderer;
|
||||
class EntityItemID;
|
||||
|
||||
|
@ -64,8 +66,8 @@ private:
|
|||
|
||||
std::set<int, SequenceLessThan> _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;
|
||||
};
|
||||
|
|
|
@ -21,121 +21,146 @@ class LaserPointerScriptingInterface : public QObject, public Dependency {
|
|||
SINGLETON_DEPENDENCY
|
||||
|
||||
/**jsdoc
|
||||
* Synonym for {@link Pointers} as used for laser pointers. Deprecated.
|
||||
* The <code>LaserPointers</code> 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.
|
||||
*
|
||||
* <p class="important">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.
|
||||
* <p><strong>Warning:</strong> Pointers created using this method currently always intersect at least visible and
|
||||
* collidable things but this may not always be the case.</p>
|
||||
* @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 <code>0</code>.
|
||||
*/
|
||||
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<PointerManager>()->enablePointer(uid); }
|
||||
|
||||
/**jsdoc
|
||||
* @function LaserPointers.disableLaserPointer
|
||||
* @param {number} id
|
||||
*/
|
||||
// jsdoc @borrows from Pointers
|
||||
Q_INVOKABLE void disableLaserPointer(unsigned int uid) const { DependencyManager::get<PointerManager>()->disablePointer(uid); }
|
||||
|
||||
/**jsdoc
|
||||
* @function LaserPointers.removeLaserPointer
|
||||
* @param {number} id
|
||||
*/
|
||||
// jsdoc @borrows from Pointers
|
||||
Q_INVOKABLE void removeLaserPointer(unsigned int uid) const { DependencyManager::get<PointerManager>()->removePointer(uid); }
|
||||
|
||||
/**jsdoc
|
||||
* Edits a render state of a pointer, to change its visual appearance for the state when the pointer is intersecting
|
||||
* something.
|
||||
* <p><strong>Note:</strong> You can only edit the properties of the existing parts of the pointer; you cannot change the
|
||||
* type of any part.</p>
|
||||
* <p><strong>Note:</strong> You cannot use this method to change the appearance of a default render state.</p>
|
||||
* @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 - <p>The name of the render state to set the pointer to. This may be:</p>
|
||||
* <ul>
|
||||
* <li>The name of one of the render states set in the pointer's properties.</li>
|
||||
* <li><code>""</code>, to hide the pointer and disable emitting of events.</li>
|
||||
* </ul>
|
||||
* @param {number} id - The ID of the pointer.
|
||||
*/
|
||||
Q_INVOKABLE void setRenderState(unsigned int uid, const QString& renderState) const { DependencyManager::get<PointerManager>()->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<PointerManager>()->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<PointerManager>()->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 - <code>true</code> if the target is an avatar, <code>false</code> 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<PointerManager>()->setLockEndUUID(uid, objectID, isAvatar, offsetMat); }
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* Checks if a pointer is associated with the left hand: a pointer with <code>joint</code> property set to
|
||||
* <code>"_CONTROLLER_LEFTHAND"</code> or <code>"_CAMERA_RELATIVE_CONTROLLER_LEFTHAND"</code>.
|
||||
* @function LaserPointers.isLeftHand
|
||||
* @param {number} id
|
||||
* @returns {boolean}
|
||||
* @param {number} id - The ID of the pointer.
|
||||
* @returns {boolean} <code>true</code> if the pointer is associated with the left hand, <code>false</code> if it isn't.
|
||||
*/
|
||||
Q_INVOKABLE bool isLeftHand(unsigned int uid) { return DependencyManager::get<PointerManager>()->isLeftHand(uid); }
|
||||
|
||||
/**jsdoc
|
||||
* Checks if a pointer is associated with the right hand: a pointer with <code>joint</code> property set to
|
||||
* <code>"_CONTROLLER_RIGHTHAND"</code> or <code>"_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND"</code>.
|
||||
* @function LaserPointers.isRightHand
|
||||
* @param {number} id
|
||||
* @returns {boolean}
|
||||
* @param {number} id - The ID of the pointer.
|
||||
* @returns {boolean} <code>true</code> if the pointer is associated with the right hand, <code>false</code> if it isn't.
|
||||
*/
|
||||
Q_INVOKABLE bool isRightHand(unsigned int uid) { return DependencyManager::get<PointerManager>()->isRightHand(uid); }
|
||||
|
||||
/**jsdoc
|
||||
* Checks if a pointer is associated with the system mouse: a pointer with <code>joint</code> property set to
|
||||
* <code>"Mouse"</code>.
|
||||
* @function LaserPointers.isMouse
|
||||
* @param {number} id
|
||||
* @returns {boolean}
|
||||
* @param {number} id - The ID of the pointer.
|
||||
* @returns {boolean} <code>true</code> if the pointer is associated with the system mouse, <code>false</code> if it isn't.
|
||||
*/
|
||||
Q_INVOKABLE bool isMouse(unsigned int uid) { return DependencyManager::get<PointerManager>()->isMouse(uid); }
|
||||
};
|
||||
|
|
|
@ -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] - <code>true</code> if this pick should start enabled, <code>false</code> 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] <code>0</code> for the left hand, <code>1</code> for the right hand, invalid (<code>-1</code>)
|
||||
|
@ -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] - <code>true</code> if this pick should start enabled, <code>false</code> 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] - <code>true</code> if this pick should start enabled, <code>false</code> if it should
|
||||
|
|
|
@ -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 <code>PICK_PRECISE</code> or <code>PICK_COARSE</code> 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.
|
||||
* <p><strong>Note:</strong> Not used by stylus picks.</p>
|
||||
* @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.
|
||||
* <p><strong>Note:</strong> Stylus picks only intersect with objects in their include list.</p>
|
||||
* Sets a list of entity and avatar IDs that a pick should include during intersection, instead of intersecting with
|
||||
* everything.
|
||||
* <p><strong>Note:</strong> Stylus picks only intersect with items in their include list.</p>
|
||||
* @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
|
||||
* <code>"_CONTROLLER_LEFTHAND"</code> or <code>"_CAMERA_RELATIVE_CONTROLLER_LEFTHAND"</code>, or a stylus pick with hand
|
||||
* set to <code>0</code>.
|
||||
* Checks if a pick is associated with the left hand: a ray or parabola pick with <code>joint</code> property set to
|
||||
* <code>"_CONTROLLER_LEFTHAND"</code> or <code>"_CAMERA_RELATIVE_CONTROLLER_LEFTHAND"</code>, or a stylus pick with
|
||||
* <code>hand</code> property set to <code>0</code>.
|
||||
* @function Picks.isLeftHand
|
||||
* @param {number} id - The ID of the pick.
|
||||
* @returns {boolean} <code>true</code> if the pick is associated with the left hand, <code>false</code> 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
|
||||
* <code>"_CONTROLLER_RIGHTHAND"</code> or <code>"_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND"</code>, or a stylus pick with hand
|
||||
* set to <code>1</code>.
|
||||
* Checks if a pick is associated with the right hand: a ray or parabola pick with <code>joint</code> property set to
|
||||
* <code>"_CONTROLLER_RIGHTHAND"</code> or <code>"_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND"</code>, or a stylus pick with
|
||||
* <code>hand</code> property set to <code>1</code>.
|
||||
* @function Picks.isRightHand
|
||||
* @param {number} id - The ID of the pick.
|
||||
* @returns {boolean} <code>true</code> if the pick is associated with the right hand, <code>false</code> 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 <code>"Mouse"</code>.
|
||||
* Checks if a pick is associated with the system mouse: a ray or parabola pick with <code>joint</code> property set to
|
||||
* <code>"Mouse"</code>.
|
||||
* @function Picks.isMouse
|
||||
* @param {number} id - The ID of the pick.
|
||||
* @returns {boolean} <code>true</code> if the pick is associated with the system mouse, <code>false</code> if it isn't.
|
||||
|
|
|
@ -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] - <code>true</code> if the pointer generates {@link Entities} hover events,
|
||||
* <code>false</code> 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 <code>type</code> 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 <code>type</code> field), which <b>must</b> be <code>"line3d"</code>.
|
||||
* 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 <code>type</code> 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]
|
||||
* <p>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 <code>type</code> property must be specified.</p>
|
||||
* <p>When getting using {@link Pointers.getPointerProperties}, the ID of the overlay rendered at the start of the ray;
|
||||
* <code>null</code> if there is no overlay.
|
||||
*
|
||||
* @property {Overlays.OverlayProperties|Uuid} [path]
|
||||
* <p>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 <code>type</code> property must be specified and be
|
||||
* <code>"line3d"</code>.</p>
|
||||
* <p>When getting using {@link Pointers.getPointerProperties}, the ID of the overlay rendered for the path of the ray;
|
||||
* <code>null</code> if there is no overlay.
|
||||
*
|
||||
* @property {Overlays.OverlayProperties|Uuid} [end]
|
||||
* <p>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 <code>type</code> property must be specified.</p>
|
||||
* <p>When getting using {@link Pointers.getPointerProperties}, the ID of the overlay rendered at the end of the ray;
|
||||
* <code>null</code> 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. <code>0-1</code>. If 0 or 1,
|
||||
* the normal will follow exactly.
|
||||
* @property {boolean} [enabled=false]
|
||||
* @property {Pointers.RayPointerRenderState[]|Object.<string, Pointers.RayPointerRenderState>} [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.<string, Pointers.DefaultRayPointerRenderState>} [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] - <code>true</code> if the overlay rendered at the end of the ray rotates about the
|
||||
* world y-axis to always face the avatar; <code>false</code> if it maintains its world orientation.
|
||||
* @property {boolean} [centerEndY=true] - <code>true</code> if the overlay rendered at the end of the ray is centered on
|
||||
* the ray end; <code>false</code> if the overlay is positioned against the surface if <code>followNormal</code> is
|
||||
* <code>true</code>, or above the ray end if <code>followNormal</code> is <code>false</code>.
|
||||
* @property {boolean} [lockEnd=false] - <code>true</code> if the end of the ray is locked to the center of the object at
|
||||
* which the ray is pointing; <code>false</code> if the end of the ray is at the intersected surface.
|
||||
* @property {boolean} [distanceScaleEnd=false] - <code>true</code> if the dimensions of the overlay at the end of the ray
|
||||
* scale linearly with distance; <code>false</code> if they aren't.
|
||||
* @property {boolean} [scaleWithParent=false] - <code>true</code> 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; <code>false</code> if they don't scale.
|
||||
* @property {boolean} [scaleWithAvatar=false] - A synonym for <code>scalewithParent</code>.
|
||||
* <p class="important">Deprecated: This property is deprecated and will be removed.</p>
|
||||
* @property {boolean} [followNormal=false] - <code>true</code> if the overlay rendered at the end of the ray rotates to
|
||||
* follow the normal of the surface if one is intersected; <code>false</code> 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 <code>0</code> or <code>1</code>, the overlay rotation follows instantaneously;
|
||||
* for other values, the larger the value the more quickly the rotation follows.
|
||||
* @property {Pointers.RayPointerRenderState[]|Object.<string, Pointers.RayPointerRenderState>} [renderStates]
|
||||
* <p>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.</p>
|
||||
* <p>When setting using {@link Pointers.createPointer}, an array of
|
||||
* {@link Pointers.RayPointerRenderState|RayPointerRenderState} values.</p>
|
||||
* <p>When getting using {@link Pointers.getPointerProperties}, an object mapping render state names to
|
||||
* {@link Pointers.RayPointerRenderState|RayPointerRenderState} values.</p>
|
||||
* @property {Pointers.DefaultRayPointerRenderState[]|Object.<string, Pointers.DefaultRayPointerRenderState>}
|
||||
* [defaultRenderStates]
|
||||
* <p>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.</p>
|
||||
* <p>When setting using {@link Pointers.createPointer}, an array of
|
||||
* {@link Pointers.DefaultRayPointerRenderState|DefaultRayPointerRenderState} values.</p>
|
||||
* <p>When getting using {@link Pointers.getPointerProperties}, an object mapping render state names to
|
||||
* {@link Pointers.DefaultRayPointerRenderState|DefaultRayPointerRenderState} values.</p>
|
||||
* @property {boolean} [hover=false] - <code>true</code> if the pointer generates {@link Entities} hover events,
|
||||
* <code>false</code> 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 <code>true</code>, 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 <code>0.0</code> – <code>1.0</code>.
|
||||
* @property {number} [width=0.01] - The width of the parabola, in meters.
|
||||
* @property {boolean} [isVisibleInSecondaryCamera=false] - <code>true</code> if the parabola is rendered in the secondary
|
||||
* camera, <code>false</code> if it isn't.
|
||||
* @property {boolean} [drawInFront=false] - <code>true</code> if the parabola is rendered in front of objects in the world,
|
||||
* but behind the HUD, <code>false</code> 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 <code>type</code> 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 <code>type</code> 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]
|
||||
* <p>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 <code>type</code> property must be specified.</p>
|
||||
* <p>When getting using {@link Pointers.getPointerProperties}, the ID of the overlay rendered at the start of the
|
||||
* parabola; <code>null</code> if there is no overlay.
|
||||
* @property {Pointers.ParabolaPointerPath|Uuid} [path]
|
||||
* <p>When creating or editing using {@link Pointers.createPointer} or {@link Pointers.editRenderState}, the properties of
|
||||
* the rendered path of the parabola pointer.</p>
|
||||
* <p>This property is not provided when getting using {@link Pointers.getPointerProperties}.
|
||||
* @property {Overlays.OverlayProperties|Uuid} [end]
|
||||
* <p>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 <code>type</code> property must be specified.</p>
|
||||
* <p>When getting using {@link Pointers.getPointerProperties}, the ID of the overlay rendered at the end of the parabola;
|
||||
* <code>null</code> 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. <code>0-1</code>. If 0 or 1,
|
||||
* the normal will follow exactly.
|
||||
* @property {boolean} [enabled=false]
|
||||
* @property {Pointers.ParabolaPointerRenderState[]|Object.<string, Pointers.ParabolaPointerRenderState>} [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.<string, Pointers.DefaultParabolaPointerRenderState>} [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] - <code>true</code> if the overlay rendered at the end of the ray rotates about the
|
||||
* world y-axis to always face the avatar; <code>false</code> if it maintains its world orientation.
|
||||
* @property {boolean} [centerEndY=true] - <code>true</code> if the overlay rendered at the end of the ray is centered on
|
||||
* the ray end; <code>false</code> if the overlay is positioned against the surface if <code>followNormal</code> is
|
||||
* <code>true</code>, or above the ray end if <code>followNormal</code> is <code>false</code>.
|
||||
* @property {boolean} [lockEnd=false] - <code>true</code> if the end of the ray is locked to the center of the object at
|
||||
* which the ray is pointing; <code>false</code> if the end of the ray is at the intersected surface.
|
||||
* @property {boolean} [distanceScaleEnd=false] - <code>true</code> if the dimensions of the overlay at the end of the ray
|
||||
* scale linearly with distance; <code>false</code> if they aren't.
|
||||
* @property {boolean} [scaleWithParent=false] - <code>true</code> 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; <code>false</code> if they don't scale.
|
||||
* @property {boolean} [scaleWithAvatar=false] - A synonym for <code>scalewithParent</code>.
|
||||
* <p class="important">Deprecated: This property is deprecated and will be removed.</p>
|
||||
* @property {boolean} [followNormal=false] - <code>true</code> if the overlay rendered at the end of the ray rotates to
|
||||
* follow the normal of the surface if one is intersected; <code>false</code> 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 <code>0</code> or <code>1</code>, the overlay rotation follows instantaneously;
|
||||
* for other values, the larger the value the more quickly the rotation follows.
|
||||
* @property {Pointers.ParabolaPointerRenderState[]|Object.<string, Pointers.ParabolaPointerRenderState>} [renderStates]
|
||||
* <p>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.</p>
|
||||
* <p>When setting using {@link Pointers.createPointer}, an array of
|
||||
* {@link Pointers.ParabolaPointerRenderState|ParabolaPointerRenderState} values.</p>
|
||||
* <p>When getting using {@link Pointers.getPointerProperties}, an object mapping render state names to
|
||||
* {@link Pointers.ParabolaPointerRenderState|ParabolaPointerRenderState} values.</p>
|
||||
* @property {Pointers.DefaultParabolaPointerRenderState[]|Object.<string, Pointers.DefaultParabolaPointerRenderState>}
|
||||
* [defaultRenderStates]
|
||||
* <p>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.</p>
|
||||
* <p>When setting using {@link Pointers.createPointer}, an array of
|
||||
* {@link Pointers.DefaultParabolaPointerRenderState|DefaultParabolaPointerRenderState} values.</p>
|
||||
* <p>When getting using {@link Pointers.getPointerProperties}, an object mapping render state names to
|
||||
* {@link Pointers.DefaultParabolaPointerRenderState|DefaultParabolaPointerRenderState} values.</p>
|
||||
* @property {boolean} [hover=false] - <code>true</code> if the pointer generates {@link Entities} hover events,
|
||||
* <code>false</code> 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();
|
||||
|
||||
|
|
|
@ -15,8 +15,9 @@
|
|||
#include <Pick.h>
|
||||
|
||||
/**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 <code>Pointers</code> 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 <code>button</code>.
|
||||
* @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 <code>>= 1.0</code> to start the action
|
||||
* and <code>< 1.0</code> to terminate the action.
|
||||
* @property {string} button - Which button to trigger.
|
||||
* <ul>
|
||||
* <li><code>"Primary"</code>, <code>"Secondary"</code>, and <code>"Tertiary"</code> cause {@link Entities} and
|
||||
* {@link Overlays} mouse pointer events. Other button names also cause mouse events but the <code>button</code>
|
||||
* property in the event will be <code>"None"</code>.</li>
|
||||
* <li><code>"Focus"</code> will try to give focus to the entity or overlay which the pointer is intersecting.</li>
|
||||
* </ul>
|
||||
*/
|
||||
|
||||
/**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.
|
||||
* <p><strong>Warning:</strong> Pointers created using this method currently always intersect at least visible and
|
||||
* collidable things but this may not always be the case.</p>
|
||||
* @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 <b>and</b> 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 <code>type</code>, 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 <code>0</code>.
|
||||
*
|
||||
* @example <caption>Create a left hand Ray Pointer that triggers events on left controller trigger click and changes color when it's intersecting something.</caption>
|
||||
*
|
||||
* var end = {
|
||||
* @example <caption>Create a ray pointer on the left hand that changes color when it's intersecting and that triggers
|
||||
* events.<br />
|
||||
* Note: Stop controllerScripts.js from running to disable similar behavior from it.</caption>
|
||||
* 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<PointerManager>()->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<PointerManager>()->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<PointerManager>()->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.
|
||||
* <p><strong>Note:</strong> You can only edit the properties of the existing parts of the pointer; you cannot change the
|
||||
* type of any part.</p>
|
||||
* <p><strong>Note:</strong> You cannot use this method to change the appearance of a default render state.</p>
|
||||
* <p><strong>Note:</strong> Not able to be used with stylus pointers.</p>
|
||||
* @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 <code>renderStates</code> 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 <caption>Change the dimensions of a ray pointer's intersecting end overlay.</caption>
|
||||
* 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 - <p>The name of the render state to set the pointer to.</p>
|
||||
* <p>For {@link Pointers.RayPointerProperties|ray} and {@link Pointers.ParabolaPointerProperties|parabola} pointers,
|
||||
* this may be:</p>
|
||||
* <ul>
|
||||
* <li>The name of one of the render states set in the pointer's properties.</li>
|
||||
* <li><code>""</code>, to hide the pointer and disable emitting of events.</li>
|
||||
* </ul>
|
||||
* <p>For {@link Pointers.StylusPointerProperties|stylus} pointers, the values may be:</p>
|
||||
* <ul>
|
||||
* <li><code>"events on"</code>, to render and emit events (the default).</li>
|
||||
* <li><code>"events off"</code>, to render but don't emit events.</li>
|
||||
* <li><code>"disabled"</code>, to not render and not emit events.</li>
|
||||
* </ul>
|
||||
* @example <caption>Switch a ray pointer between having a path and not having a path.</caption>
|
||||
* 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<PointerManager>()->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 <code>PICK_PRECISE</code> or <code>PICK_COARSE</code> 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 - <code>true</code> to use precision picking, <code>false</code> to use coarse picking.
|
||||
*/
|
||||
Q_INVOKABLE void setPrecisionPicking(unsigned int uid, bool precisionPicking) const { DependencyManager::get<PointerManager>()->setPrecisionPicking(uid, precisionPicking); }
|
||||
|
||||
/**jsdoc
|
||||
* Sets the length of this Pointer. No effect on Stylus Pointers.
|
||||
* Sets the length of a pointer.
|
||||
* <p><strong>Note:</strong> Not used by stylus pointers.</p>
|
||||
* @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<PointerManager>()->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.
|
||||
* <p><strong>Note:</strong> Not used by stylus pointers.</p>
|
||||
* @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 <b>only</b> 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.
|
||||
* <p><strong>Note:</strong> Stylus pointers only intersect with items in their include list.</p>
|
||||
* @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.
|
||||
* <p><strong>Note:</strong> Not used by stylus pointers.</p>
|
||||
* @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 - <code>true</code> if the target is an avatar, <code>false</code> 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<PointerManager>()->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 <code>joint</code> property set to
|
||||
* <code>"_CONTROLLER_LEFTHAND"</code> or <code>"_CAMERA_RELATIVE_CONTROLLER_LEFTHAND"</code>, or a stylus pointer with
|
||||
* <code>hand</code> property set to <code>0</code>.
|
||||
* @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} <code>true</code> if the pointer is associated with the left hand, <code>false</code> if it isn't.
|
||||
*/
|
||||
Q_INVOKABLE bool isLeftHand(unsigned int uid) { return DependencyManager::get<PointerManager>()->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 <code>joint</code> property set to
|
||||
* <code>"_CONTROLLER_RIGHTHAND"</code> or <code>"_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND"</code>, or a stylus pointer with
|
||||
* <code>hand</code> property set to <code>1</code>.
|
||||
* @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} <code>true</code> if the pointer is associated with the right hand, <code>false</code> if it isn't.
|
||||
*/
|
||||
Q_INVOKABLE bool isRightHand(unsigned int uid) { return DependencyManager::get<PointerManager>()->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 <code>joint</code> property set
|
||||
* to <code>"Mouse"</code>.
|
||||
* @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} <code>true</code> if the pointer is associated with the system mouse, <code>false</code> if it isn't.
|
||||
*/
|
||||
Q_INVOKABLE bool isMouse(unsigned int uid) { return DependencyManager::get<PointerManager>()->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 <code>renderStates</code> and
|
||||
* <code>defaultRenderStates</code> for ray and parabola pointers, <code>{}</code> for stylus pointers.
|
||||
* @example <caption>Report the properties of a parabola pointer.</caption>
|
||||
* 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;
|
||||
};
|
||||
|
|
|
@ -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 - <code>true</code> to use precision picking, <code>false</code> 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
|
||||
* <code>"_CONTROLLER_LEFTHAND"</code> or <code>"_CAMERA_RELATIVE_CONTROLLER_LEFTHAND"</code>, or a stylus pick with hand
|
||||
* set to <code>0</code>.
|
||||
* Checks if a pick is associated with the left hand: a ray or parabola pick with <code>joint</code> property set to
|
||||
* <code>"_CONTROLLER_LEFTHAND"</code> or <code>"_CAMERA_RELATIVE_CONTROLLER_LEFTHAND"</code>, or a stylus pick with
|
||||
* <code>hand</code> property set to <code>0</code>.
|
||||
* @function RayPick.isLeftHand
|
||||
* @param {number} id - The ID of the ray pick.
|
||||
* @returns {boolean} <code>true</code> if the pick is associated with the left hand, <code>false</code> 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
|
||||
* <code>"_CONTROLLER_RIGHTHAND"</code> or <code>"_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND"</code>, or a stylus pick with hand
|
||||
* set to <code>1</code>.
|
||||
* Checks if a pick is associated with the right hand: a ray or parabola pick with <code>joint</code> property set to
|
||||
* <code>"_CONTROLLER_RIGHTHAND"</code> or <code>"_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND"</code>, or a stylus pick with
|
||||
* <code>hand</code> property set to <code>1</code>.
|
||||
* @function RayPick.isRightHand
|
||||
* @param {number} id - The ID of the ray pick.
|
||||
* @returns {boolean} <code>true</code> if the pick is associated with the right hand, <code>false</code> 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 <code>"Mouse"</code>.
|
||||
* Checks if a pick is associated with the system mouse: a ray or parabola pick with <code>joint</code> property set to
|
||||
* <code>"Mouse"</code>.
|
||||
* @function RayPick.isMouse
|
||||
* @param {number} id - The ID of the ray pick.
|
||||
* @returns {boolean} <code>true</code> if the pick is associated with the system mouse, <code>false</code> if it isn't.
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -32,6 +32,11 @@ CLauncherApp theApp;
|
|||
// CLauncherApp initialization
|
||||
|
||||
BOOL CLauncherApp::InitInstance() {
|
||||
// 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);
|
||||
bool isUninstalling = false;
|
||||
|
|
|
@ -119,15 +119,22 @@ 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;
|
||||
|
@ -135,6 +142,33 @@ BOOL CLauncherDlg::PreTranslateMessage(MSG* pMsg) {
|
|||
OnNextClicked();
|
||||
return TRUE;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
@ -629,7 +663,7 @@ void CLauncherDlg::OnTimer(UINT_PTR nIDEvent) {
|
|||
::SetForegroundWindow(_applicationWND);
|
||||
::SetActiveWindow(_applicationWND);
|
||||
}
|
||||
if (LauncherUtils::IsProcessRunning(L"interface.exe")) {
|
||||
if (LauncherUtils::isProcessWindowOpened(L"interface.exe")) {
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
@ -653,7 +687,7 @@ void CLauncherDlg::OnTimer(UINT_PTR nIDEvent) {
|
|||
}
|
||||
_splashStep++;
|
||||
} else if (theApp._manager.shouldShutDown()) {
|
||||
if (LauncherUtils::IsProcessRunning(L"interface.exe")) {
|
||||
if (LauncherUtils::isProcessWindowOpened(L"interface.exe")) {
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,12 +60,18 @@ protected:
|
|||
DrawStep _drawStep { DrawStep::DrawLogo };
|
||||
BOOL getTextFormat(int ResID, TextFormat& formatOut);
|
||||
void showWindows(std::vector<CStatic*> 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;
|
||||
|
|
|
@ -15,13 +15,10 @@
|
|||
#include "LauncherManager.h"
|
||||
|
||||
|
||||
LauncherManager::LauncherManager()
|
||||
{
|
||||
LauncherManager::LauncherManager() {
|
||||
}
|
||||
|
||||
|
||||
LauncherManager::~LauncherManager()
|
||||
{
|
||||
LauncherManager::~LauncherManager() {
|
||||
}
|
||||
|
||||
void LauncherManager::init() {
|
||||
|
@ -113,8 +110,11 @@ BOOL LauncherManager::installLauncher() {
|
|||
// The installer is not running on the desired location and has to be installed
|
||||
// Kill of running before self-copy
|
||||
addToLog(_T("Installing Launcher."));
|
||||
if (LauncherUtils::IsProcessRunning(LAUNCHER_EXE_FILENAME)) {
|
||||
ShellExecute(NULL, NULL, L"taskkill", L"/F /T /IM " + LAUNCHER_EXE_FILENAME, NULL, SW_HIDE);
|
||||
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);
|
||||
}
|
||||
|
@ -151,7 +151,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;
|
||||
|
@ -159,13 +159,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;
|
||||
|
@ -308,7 +308,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();
|
||||
|
|
|
@ -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<ProcessData*>(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<LPARAM>(&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
|
||||
|
|
|
@ -66,6 +66,11 @@ public:
|
|||
void setCallback(std::function<void(int)> fn) { callback = std::bind(fn, std::placeholders::_1); }
|
||||
};
|
||||
|
||||
struct ProcessData {
|
||||
int processID = -1;
|
||||
BOOL isOpened = FALSE;
|
||||
};
|
||||
|
||||
static BOOL parseJSON(const CString& jsonTxt, Json::Value& jsonObject);
|
||||
static ResponseError makeHTTPCall(const CString& callerName, const CString& mainUrl,
|
||||
const CString& dirUrl, const CString& contentType,
|
||||
|
@ -73,11 +78,14 @@ 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<std::string>& files);
|
||||
static BOOL deleteRegistryKey(const CString& registryPath);
|
||||
|
|
|
@ -280,6 +280,10 @@ AvatarSharedPointer AvatarHashMap::parseAvatarData(QSharedPointer<ReceivedMessag
|
|||
|
||||
return avatar;
|
||||
} else {
|
||||
// Shouldn't happen if mixer functioning correctly - debugging for BUGZ-781:
|
||||
qCDebug(avatars) << "Discarding received avatar data" << sessionUUID << (sessionUUID == _lastOwnerSessionUUID ? "(is self)" : "")
|
||||
<< "isIgnoringNode = " << nodeList->isIgnoringNode(sessionUUID);
|
||||
|
||||
// create a dummy AvatarData class to throw this data on the ground
|
||||
AvatarData dummyData;
|
||||
int bytesRead = dummyData.parseDataFromBuffer(byteArray);
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -199,9 +199,8 @@ void ImageEntityRenderer::doRender(RenderArgs* args) {
|
|||
float x = _keepAspectRatio ? fromImage.width() / (2.0f * maxSize) : 0.5f;
|
||||
float y = _keepAspectRatio ? fromImage.height() / (2.0f * maxSize) : 0.5f;
|
||||
|
||||
glm::vec2 texCoordBottomLeft((fromImage.x() + 0.5f) / imageWidth, -(fromImage.y() + 0.5f) / imageHeight);
|
||||
glm::vec2 texCoordTopRight((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<GeometryCache>()->renderQuad(
|
||||
*batch, glm::vec2(-x, -y), glm::vec2(x, y), texCoordBottomLeft, texCoordTopRight,
|
||||
|
|
|
@ -277,51 +277,60 @@ entities::TextPayload::~TextPayload() {
|
|||
}
|
||||
|
||||
ItemKey entities::TextPayload::getKey() const {
|
||||
auto renderable = DependencyManager::get<EntityTreeRenderer>()->renderableForEntityId(_entityID);
|
||||
if (renderable) {
|
||||
auto textRenderable = std::static_pointer_cast<TextEntityRenderer>(renderable);
|
||||
ItemKey::Builder key;
|
||||
// Similar to EntityRenderer::getKey()
|
||||
if (textRenderable->isTextTransparent()) {
|
||||
key = ItemKey::Builder::transparentShape().withSubMetaCulled().withTagBits(textRenderable->getTagMask()).withLayer(textRenderable->getHifiRenderLayer());
|
||||
} else if (textRenderable->_canCastShadow) {
|
||||
key = ItemKey::Builder::opaqueShape().withSubMetaCulled().withTagBits(textRenderable->getTagMask()).withShadowCaster().withLayer(textRenderable->getHifiRenderLayer());
|
||||
} else {
|
||||
key = ItemKey::Builder::opaqueShape().withSubMetaCulled().withTagBits(textRenderable->getTagMask()).withLayer(textRenderable->getHifiRenderLayer());
|
||||
}
|
||||
auto entityTreeRenderer = DependencyManager::get<EntityTreeRenderer>();
|
||||
if (entityTreeRenderer) {
|
||||
auto renderable = entityTreeRenderer->renderableForEntityId(_entityID);
|
||||
if (renderable) {
|
||||
auto textRenderable = std::static_pointer_cast<TextEntityRenderer>(renderable);
|
||||
ItemKey::Builder key;
|
||||
// Similar to EntityRenderer::getKey()
|
||||
if (textRenderable->isTextTransparent()) {
|
||||
key = ItemKey::Builder::transparentShape().withSubMetaCulled().withTagBits(textRenderable->getTagMask()).withLayer(textRenderable->getHifiRenderLayer());
|
||||
} else if (textRenderable->_canCastShadow) {
|
||||
key = ItemKey::Builder::opaqueShape().withSubMetaCulled().withTagBits(textRenderable->getTagMask()).withShadowCaster().withLayer(textRenderable->getHifiRenderLayer());
|
||||
} else {
|
||||
key = ItemKey::Builder::opaqueShape().withSubMetaCulled().withTagBits(textRenderable->getTagMask()).withLayer(textRenderable->getHifiRenderLayer());
|
||||
}
|
||||
|
||||
if (!textRenderable->_visible) {
|
||||
key.withInvisible();
|
||||
if (!textRenderable->_visible) {
|
||||
key.withInvisible();
|
||||
}
|
||||
return key;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
return ItemKey::Builder::opaqueShape();
|
||||
}
|
||||
|
||||
Item::Bound entities::TextPayload::getBound() const {
|
||||
auto renderable = DependencyManager::get<EntityTreeRenderer>()->renderableForEntityId(_entityID);
|
||||
if (renderable) {
|
||||
return std::static_pointer_cast<TextEntityRenderer>(renderable)->getBound();
|
||||
auto entityTreeRenderer = DependencyManager::get<EntityTreeRenderer>();
|
||||
if (entityTreeRenderer) {
|
||||
auto renderable = entityTreeRenderer->renderableForEntityId(_entityID);
|
||||
if (renderable) {
|
||||
return std::static_pointer_cast<TextEntityRenderer>(renderable)->getBound();
|
||||
}
|
||||
}
|
||||
return Item::Bound();
|
||||
}
|
||||
|
||||
ShapeKey entities::TextPayload::getShapeKey() const {
|
||||
auto renderable = DependencyManager::get<EntityTreeRenderer>()->renderableForEntityId(_entityID);
|
||||
if (renderable) {
|
||||
auto textRenderable = std::static_pointer_cast<TextEntityRenderer>(renderable);
|
||||
auto entityTreeRenderer = DependencyManager::get<EntityTreeRenderer>();
|
||||
if (entityTreeRenderer) {
|
||||
auto renderable = entityTreeRenderer->renderableForEntityId(_entityID);
|
||||
if (renderable) {
|
||||
auto textRenderable = std::static_pointer_cast<TextEntityRenderer>(renderable);
|
||||
|
||||
auto builder = render::ShapeKey::Builder().withOwnPipeline();
|
||||
if (textRenderable->isTextTransparent()) {
|
||||
builder.withTranslucent();
|
||||
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();
|
||||
}
|
||||
if (textRenderable->_unlit) {
|
||||
builder.withUnlit();
|
||||
}
|
||||
if (textRenderable->_primitiveMode == PrimitiveMode::LINES) {
|
||||
builder.withWireframe();
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
return ShapeKey::Builder::invalid();
|
||||
}
|
||||
|
@ -336,7 +345,11 @@ void entities::TextPayload::render(RenderArgs* args) {
|
|||
return;
|
||||
}
|
||||
|
||||
auto renderable = DependencyManager::get<EntityTreeRenderer>()->renderableForEntityId(_entityID);
|
||||
auto entityTreeRenderer = DependencyManager::get<EntityTreeRenderer>();
|
||||
if (!entityTreeRenderer) {
|
||||
return;
|
||||
}
|
||||
auto renderable = entityTreeRenderer->renderableForEntityId(_entityID);
|
||||
if (!renderable) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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,6 +31,8 @@ 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;
|
||||
|
@ -38,10 +41,19 @@ namespace platform { namespace keys{
|
|||
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;
|
||||
|
|
|
@ -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<std::string>() : "");
|
||||
|
||||
auto gpuInfo = platform::getGPU(0);
|
||||
auto gpuInfo = platform::getGPU(getMasterGPU());
|
||||
const auto gpuModel = (gpuInfo.count(keys::gpu::model) ? gpuInfo[keys::gpu::model].get<std::string>() : "");
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "../PlatformKeys.h"
|
||||
#include <GPUIdent.h>
|
||||
#include <QSysInfo>
|
||||
#include <QtCore/QtGlobal>
|
||||
|
||||
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();
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace platform {
|
|||
|
||||
public:
|
||||
void enumerateCpus() override;
|
||||
void enumerateGpus() override;
|
||||
void enumerateGpusAndDisplays() override;
|
||||
void enumerateMemory() override;
|
||||
void enumerateComputer() override;
|
||||
};
|
||||
|
|
|
@ -12,6 +12,9 @@
|
|||
#include <thread>
|
||||
#include <string>
|
||||
#include <CPUIdent.h>
|
||||
|
||||
#include <QtCore/QtGlobal>
|
||||
|
||||
#include <GPUIdent.h>
|
||||
#include <QSysInfo>
|
||||
|
||||
|
@ -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();
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace platform {
|
|||
|
||||
public:
|
||||
void enumerateCpus() override;
|
||||
void enumerateGpus() override;
|
||||
void enumerateGpusAndDisplays() override;
|
||||
void enumerateMemory() override;
|
||||
void enumerateComputer() override;
|
||||
};
|
||||
|
|
|
@ -12,16 +12,22 @@
|
|||
#include <thread>
|
||||
#include <string>
|
||||
#include <CPUIdent.h>
|
||||
#include <GPUIdent.h>
|
||||
|
||||
#include <QtCore/QtGlobal>
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
#include <unistd.h>
|
||||
#include <cpuid.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <regex>
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#include <QSysInfo>
|
||||
#include <QString>
|
||||
#include <OpenGL/OpenGL.h>
|
||||
#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<GLuint> 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<CGDirectDisplayID> 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<std::string>());
|
||||
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<int> 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<ChipsetModelDesc> 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
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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,6 +32,8 @@ 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";
|
||||
|
@ -39,10 +42,19 @@ namespace platform { namespace keys {
|
|||
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";
|
||||
|
@ -117,6 +129,10 @@ json platform::getCPU(int index) {
|
|||
return _instance->getCPU(index);
|
||||
}
|
||||
|
||||
int platform::getMasterCPU() {
|
||||
return _instance->getMasterCPU();
|
||||
}
|
||||
|
||||
int platform::getNumGPUs() {
|
||||
return _instance->getNumGPUs();
|
||||
}
|
||||
|
@ -125,6 +141,10 @@ json platform::getGPU(int index) {
|
|||
return _instance->getGPU(index);
|
||||
}
|
||||
|
||||
int platform::getMasterGPU() {
|
||||
return _instance->getMasterGPU();
|
||||
}
|
||||
|
||||
int platform::getNumDisplays() {
|
||||
return _instance->getNumDisplays();
|
||||
}
|
||||
|
@ -133,6 +153,10 @@ json platform::getDisplay(int index) {
|
|||
return _instance->getDisplay(index);
|
||||
}
|
||||
|
||||
int platform::getMasterDisplay() {
|
||||
return _instance->getMasterDisplay();
|
||||
}
|
||||
|
||||
json platform::getMemory() {
|
||||
return _instance->getMemory();
|
||||
}
|
||||
|
|
|
@ -16,18 +16,83 @@
|
|||
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()];
|
||||
|
||||
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<bool>()) {
|
||||
_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()) {
|
||||
|
@ -57,6 +122,7 @@ json Instance::getGPU(int index) {
|
|||
return _gpus.at(index);
|
||||
}
|
||||
|
||||
|
||||
json Instance::getDisplay(int index) {
|
||||
assert(index <(int) _displays.size());
|
||||
|
||||
|
@ -98,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,
|
||||
|
||||
|
|
|
@ -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,7 @@ 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;
|
||||
|
@ -55,6 +59,14 @@ protected:
|
|||
std::vector<json> _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
|
||||
|
|
|
@ -11,21 +11,31 @@
|
|||
|
||||
#include <thread>
|
||||
#include <string>
|
||||
|
||||
#include <CPUIdent.h>
|
||||
#include <GPUIdent.h>
|
||||
|
||||
#include <QtCore/QtGlobal>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <sstream>
|
||||
#include <qstring>
|
||||
#include <qsysinfo>
|
||||
#include <Windows.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <stdio.h>
|
||||
#include <QSysInfo>
|
||||
#include <dxgi1_3.h>
|
||||
#pragma comment(lib, "dxgi.lib")
|
||||
#include <shellscalingapi.h>
|
||||
#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();
|
||||
|
@ -33,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<std::string>());
|
||||
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<int> validAdapterList;
|
||||
using AdapterEntry = std::pair<std::pair<DXGI_ADAPTER_DESC1, LARGE_INTEGER>, std::vector<DXGI_OUTPUT_DESC>>;
|
||||
std::vector<AdapterEntry> 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<std::string>());
|
||||
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<int> 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);
|
||||
|
@ -60,16 +200,18 @@ 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();
|
||||
|
@ -78,23 +220,23 @@ void WINInstance::enumerateNics() {
|
|||
// 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);
|
||||
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);
|
||||
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...
|
||||
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<std::string>().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);
|
||||
QByteArray wmac = QByteArray((const char*)(pAdapter->Address), pAdapter->AddressLength);
|
||||
QString wraw = wmac.toHex();
|
||||
if (qtraw == wraw) {
|
||||
nic[keys::nic::name] = pAdapter->Description;
|
||||
|
@ -108,4 +250,4 @@ void WINInstance::enumerateNics() {
|
|||
free(pAdapterInfo);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace platform {
|
|||
|
||||
public:
|
||||
void enumerateCpus() override;
|
||||
void enumerateGpus() override;
|
||||
void enumerateGpusAndDisplays() override;
|
||||
void enumerateMemory() override;
|
||||
void enumerateComputer () override;
|
||||
void enumerateNics() override;
|
||||
|
|
|
@ -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 = {};
|
||||
|
|
|
@ -51,6 +51,7 @@ Rectangle {
|
|||
}
|
||||
Prop.PropFolderPanel {
|
||||
label: "Platform"
|
||||
isUnfold: true
|
||||
panelFrameData: Component {
|
||||
Platform {
|
||||
}
|
||||
|
|
|
@ -483,6 +483,25 @@ function maybeUpdateOutputDeviceMutedOverlay() {
|
|||
}
|
||||
|
||||
|
||||
var oldAutomaticLODAdjust;
|
||||
var oldLODLevel;
|
||||
var DEFAULT_AUTO_LOD_ADJUST = false;
|
||||
var DEFAULT_LOD_LEVEL = 0.5;
|
||||
function modifyLODSettings() {
|
||||
oldAutomaticLODAdjust = LODManager.automaticLODAdjust;
|
||||
oldLODLevel = LODManager.lodQualityLevel;
|
||||
|
||||
LODManager.automaticLODAdjust = DEFAULT_AUTO_LOD_ADJUST;
|
||||
LODManager.lodQualityLevel = DEFAULT_LOD_LEVEL;
|
||||
}
|
||||
|
||||
|
||||
function restoreLODSettings() {
|
||||
LODManager.automaticLODAdjust = oldAutomaticLODAdjust;
|
||||
LODManager.lodQualityLevel = oldLODLevel;
|
||||
}
|
||||
|
||||
|
||||
var simplifiedNametag = Script.require("./simplifiedNametag/simplifiedNametag.js?" + Date.now());
|
||||
var SimplifiedStatusIndicator = Script.require("./simplifiedStatusIndicator/simplifiedStatusIndicator.js?" + Date.now());
|
||||
var si;
|
||||
|
@ -491,6 +510,7 @@ var oldShowBubbleTools;
|
|||
var keepExistingUIAndScriptsSetting = Settings.getValue("simplifiedUI/keepExistingUIAndScripts", false);
|
||||
function startup() {
|
||||
maybeRemoveDesktopMenu();
|
||||
modifyLODSettings();
|
||||
|
||||
if (!keepExistingUIAndScriptsSetting) {
|
||||
pauseCurrentScripts();
|
||||
|
@ -541,6 +561,7 @@ function restoreScripts() {
|
|||
|
||||
function shutdown() {
|
||||
restoreScripts();
|
||||
restoreLODSettings();
|
||||
|
||||
if (!keepExistingUIAndScriptsSetting) {
|
||||
console.log("The Simplified UI script has been shut down. If you notice any strangeness with user interface, please restart this application.");
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
WebView {
|
||||
id: entityListToolWebView
|
||||
url: QT.resolvedURL("../html/entityList.html")
|
||||
url: Qt.resolvedUrl("../html/entityList.html")
|
||||
enabled: true
|
||||
blurOnCtrlShift: false
|
||||
}
|
||||
|
|
|
@ -247,7 +247,7 @@ TabBar {
|
|||
property Component visualItem: Component {
|
||||
WebView {
|
||||
id: entityPropertiesWebView
|
||||
url: Qt.resolvedURL("../entityProperties/html/entityProperties.html")
|
||||
url: Qt.resolvedUrl("../entityProperties/html/entityProperties.html")
|
||||
enabled: true
|
||||
blurOnCtrlShift: false
|
||||
}
|
||||
|
@ -263,7 +263,7 @@ TabBar {
|
|||
property Component visualItem: Component {
|
||||
WebView {
|
||||
id: gridControlsWebView
|
||||
url: Qt.resolvedURL("../../html/gridControls.html")
|
||||
url: Qt.resolvedUrl("../../html/gridControls.html")
|
||||
enabled: true
|
||||
blurOnCtrlShift: false
|
||||
}
|
||||
|
|
|
@ -66,7 +66,6 @@ def getExtensionsHeader(dialect, variant, extensions):
|
|||
extensionsHeaderMutex.release()
|
||||
return extensionHeader
|
||||
|
||||
|
||||
def getDialectAndVariantHeaders(dialect, variant, extensions=None):
|
||||
result = []
|
||||
headerPath = args.source_dir + '/libraries/shaders/headers/'
|
||||
|
@ -80,6 +79,14 @@ def getDialectAndVariantHeaders(dialect, variant, extensions=None):
|
|||
result.append(variantHeader)
|
||||
return result
|
||||
|
||||
def getDefines(defines):
|
||||
definesList = []
|
||||
if defines:
|
||||
definesSplit = defines.split("_")
|
||||
for define in definesSplit:
|
||||
definesList.append('HIFI_USE_{} 1'.format(define.upper()))
|
||||
return definesList
|
||||
|
||||
class ScribeDependenciesCache:
|
||||
cache = {}
|
||||
lock = Lock()
|
||||
|
@ -99,9 +106,9 @@ class ScribeDependenciesCache:
|
|||
with open(self.filename, "w") as f:
|
||||
f.write(json.dumps(self.cache))
|
||||
|
||||
def get(self, scribefile, dialect, variant):
|
||||
def get(self, scribefile, dialect, variant, defines):
|
||||
self.lock.acquire()
|
||||
key = self.key(scribefile, dialect, variant)
|
||||
key = self.key(scribefile, dialect, variant, defines)
|
||||
try:
|
||||
if key in self.cache:
|
||||
return self.cache[key].copy()
|
||||
|
@ -109,25 +116,26 @@ class ScribeDependenciesCache:
|
|||
self.lock.release()
|
||||
return None
|
||||
|
||||
def key(self, scribeFile, dialect, variant):
|
||||
return ':'.join([scribeFile, dialect, variant])
|
||||
def key(self, scribeFile, dialect, variant, defines):
|
||||
return ':'.join([scribeFile, dialect, variant, defines])
|
||||
|
||||
def getOrGen(self, scribefile, includeLibs, dialect, variant):
|
||||
result = self.get(scribefile, dialect, variant)
|
||||
if (None == result):
|
||||
result = self.gen(scribefile, includeLibs, dialect, variant)
|
||||
def getOrGen(self, scribefile, includeLibs, dialect, variant, defines):
|
||||
result = self.get(scribefile, dialect, variant, defines)
|
||||
if result is None:
|
||||
result = self.gen(scribefile, includeLibs, dialect, variant, defines)
|
||||
return result
|
||||
|
||||
def gen(self, scribefile, includeLibs, dialect, variant):
|
||||
def gen(self, scribefile, includeLibs, dialect, variant, defines):
|
||||
scribeArgs = getCommonScribeArgs(scribefile, includeLibs)
|
||||
scribeArgs.extend(['-M'])
|
||||
processResult = subprocess.run(scribeArgs, stdout=subprocess.PIPE)
|
||||
if (0 != processResult.returncode):
|
||||
raise RuntimeError("Unable to parse scribe dependencies")
|
||||
raise RuntimeError("Unable to parse scribe dependencies for file {} with defines: {}".format(scribefile, defines))
|
||||
result = processResult.stdout.decode("utf-8").splitlines(False)
|
||||
result.append(scribefile)
|
||||
result.extend(getDialectAndVariantHeaders(dialect, variant))
|
||||
key = self.key(scribefile, dialect, variant)
|
||||
result.extend(getDefines(defines))
|
||||
key = self.key(scribefile, dialect, variant, defines)
|
||||
self.lock.acquire()
|
||||
self.cache[key] = result.copy()
|
||||
self.lock.release()
|
||||
|
@ -166,6 +174,10 @@ def processCommand(line):
|
|||
variant = params.pop(0)
|
||||
scribeFile = args.source_dir + '/' + params.pop(0)
|
||||
unoptGlslFile = args.source_dir + '/' + params.pop(0)
|
||||
defines = ""
|
||||
if len(params) > 1 and params[0].startswith("defines:"):
|
||||
defines = params.pop(0)
|
||||
defines = defines[len("defines:"):]
|
||||
libs = params
|
||||
|
||||
upoptSpirvFile = unoptGlslFile + '.spv'
|
||||
|
@ -184,19 +196,23 @@ def processCommand(line):
|
|||
os.makedirs(scribeOutputDir)
|
||||
folderMutex.release()
|
||||
|
||||
scribeDeps = scribeDepCache.getOrGen(scribeFile, libs, dialect, variant)
|
||||
scribeDeps = scribeDepCache.getOrGen(scribeFile, libs, dialect, variant, defines)
|
||||
|
||||
# if the scribe sources (slv, slf, slh, etc), or the dialect/ variant headers are out of date
|
||||
# regenerate the scribe GLSL output
|
||||
if args.force or outOfDate(scribeDeps, outputFiles):
|
||||
print('Processing file {} dialect {} variant {}'.format(scribeFile, dialect, variant))
|
||||
print('Processing file {} dialect {} variant {} defines {}'.format(scribeFile, dialect, variant, defines))
|
||||
if args.dry_run:
|
||||
return True
|
||||
|
||||
scribeDepCache.gen(scribeFile, libs, dialect, variant)
|
||||
scribeDepCache.gen(scribeFile, libs, dialect, variant, defines)
|
||||
scribeArgs = getCommonScribeArgs(scribeFile, libs)
|
||||
for header in getDialectAndVariantHeaders(dialect, variant, args.extensions):
|
||||
scribeArgs.extend(['-H', header])
|
||||
for define in getDefines(defines):
|
||||
defineArgs = ['-D']
|
||||
defineArgs.extend(define.split(' '))
|
||||
scribeArgs.extend(defineArgs)
|
||||
scribeArgs.extend(['-o', unoptGlslFile])
|
||||
executeSubprocess(scribeArgs)
|
||||
|
||||
|
|
Loading…
Reference in a new issue