From 68d2f9581ff6bab383fbbff1f37774e2464ac0e6 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 3 Jun 2019 19:16:42 -0700 Subject: [PATCH 01/30] add ability for slp files to define shader variants --- cmake/macros/AutoScribeShader.cmake | 160 +++++++++++++++++++++++++--- tools/shadergen.py | 46 +++++--- 2 files changed, 178 insertions(+), 28 deletions(-) diff --git a/cmake/macros/AutoScribeShader.cmake b/cmake/macros/AutoScribeShader.cmake index c5bb2b4054..9a18005424 100755 --- a/cmake/macros/AutoScribeShader.cmake +++ b/cmake/macros/AutoScribeShader.cmake @@ -66,6 +66,9 @@ macro(AUTOSCRIBE_PLATFORM_SHADER) list(APPEND SHADER_GEN_LINE ${TEMP_PATH}) file(RELATIVE_PATH TEMP_PATH ${CMAKE_SOURCE_DIR} ${AUTOSCRIBE_OUTPUT_FILE}) list(APPEND SHADER_GEN_LINE ${TEMP_PATH}) + if (NOT("${DEFINES}" STREQUAL "")) + list(APPEND SHADER_GEN_LINE "defines:${DEFINES}") + endif() list(APPEND SHADER_GEN_LINE ${AUTOSCRIBE_SHADER_SEEN_LIBS}) string(CONCAT AUTOSCRIBE_SHADERGEN_COMMANDS "${AUTOSCRIBE_SHADERGEN_COMMANDS}" "${SHADER_GEN_LINE}\n") endmacro() @@ -108,6 +111,10 @@ macro(AUTOSCRIBE_SHADER) set(SHADER_TYPE geom) endif() + if (NOT("${DEFINES}" STREQUAL "")) + string(CONCAT SHADER_NAME "${SHADER_NAME}" "_${DEFINES}") + endif() + set(SCRIBE_ARGS -D GLPROFILE ${GLPROFILE} -T ${SHADER_TYPE} ${SCRIBE_INCLUDES} ) # SHADER_SCRIBED -> the output of scribe @@ -135,11 +142,72 @@ 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() +function(GENERATE_DEFINES_LIST_HELPER INPUT_LIST RETURN_LIST) + 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() + + 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 +232,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 +259,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 +276,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 +290,72 @@ 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}") + + 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 diff --git a/tools/shadergen.py b/tools/shadergen.py index f82b471f17..1f4acae915 100644 --- a/tools/shadergen.py +++ b/tools/shadergen.py @@ -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) From f2cf3bd05c37518f758c29dde3e4f3f2dfb34ffc Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 2 Jul 2019 08:10:36 +1200 Subject: [PATCH 02/30] Revise Pointers API JSDoc --- .../src/raypick/PointerScriptingInterface.cpp | 250 ++++++----- .../src/raypick/PointerScriptingInterface.h | 397 ++++++++++++++---- 2 files changed, 467 insertions(+), 180 deletions(-) diff --git a/interface/src/raypick/PointerScriptingInterface.cpp b/interface/src/raypick/PointerScriptingInterface.cpp index 1c80caff88..d904706b08 100644 --- a/interface/src/raypick/PointerScriptingInterface.cpp +++ b/interface/src/raypick/PointerScriptingInterface.cpp @@ -51,21 +51,21 @@ 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] - If true, the pointer generates {@link Entities} hover events. + * @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 +104,76 @@ unsigned int PointerScriptingInterface::createStylus(const QVariant& properties) } /**jsdoc - * A set of properties used to define the visual aspect of a Ray Pointer in the case that the Pointer is not intersecting something. Same as a {@link Pointers.RayPointerRenderState}, - * but with an additional distance field. - * + * Properties that define the visual appearance of a ray pointer when the pointer is not intersecting something. These are the + * properties of {@link Pointers.RayPointerRenderState} but with an additional property. * @typedef {object} Pointers.DefaultRayPointerRenderState - * @augments Pointers.RayPointerRenderState - * @property {number} distance The distance at which to render the end of this Ray Pointer, if one is defined. + * @property {number} distance - The distance at which to render the end of the ray pointer. + * @see {@link Pointers.RayPointerRenderState} for the remainder of the properties. */ /**jsdoc - * A set of properties which define the visual aspect of a Ray Pointer in the case that the Pointer is intersecting something. - * + * Properties that define the visual appearance of a ray pointer when the pointer is intersecting something. * @typedef {object} Pointers.RayPointerRenderState - * @property {string} name When using {@link Pointers.createPointer}, the name of this render state, used by {@link Pointers.setRenderState} and {@link Pointers.editRenderState} - * @property {Overlays.OverlayProperties|QUuid} [start] When using {@link Pointers.createPointer}, an optionally defined object to represent the beginning of the Ray Pointer, - * using the properties you would normally pass to {@link Overlays.addOverlay}, plus the type (as a type field). - * When returned from {@link Pointers.getPointerProperties}, the ID of the created object if it exists, or a null ID otherwise. - * @property {Overlays.OverlayProperties|QUuid} [path] When using {@link Pointers.createPointer}, an optionally defined object to represent the path of the Ray Pointer, - * using the properties you would normally pass to {@link Overlays.addOverlay}, plus the type (as a type field), which must be "line3d". - * When returned from {@link Pointers.getPointerProperties}, the ID of the created object if it exists, or a null ID otherwise. - * @property {Overlays.OverlayProperties|QUuid} [end] When using {@link Pointers.createPointer}, an optionally defined object to represent the end of the Ray Pointer, - * using the properties you would normally pass to {@link Overlays.addOverlay}, plus the type (as a type field). - * When returned from {@link Pointers.getPointerProperties}, the ID of the created object if it exists, or a null ID otherwise. + * @property {string} name - When creating using {@link Pointers.createPointer}, the name of the render state. + * @property {Overlays.OverlayProperties|Uuid} [start] + *

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

+ *

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

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

+ *

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

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

+ *

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

Deprecated: This property is deprecated and will be removed.

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

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

+ *

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

+ *

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

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

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

+ *

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

+ *

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

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

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

+ *

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

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

+ *

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

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

+ *

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

Deprecated: This property is deprecated and will be removed.

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

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

+ *

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

+ *

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

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

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

+ *

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

+ *

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

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

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

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

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

+ *

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

+ *

Note: Not able to be used with stylus pointers.

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

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

+ *

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

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

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

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

Note: Not used by stylus pointers.

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

Note: Not used by stylus pointers.

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

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

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

Note: Not used by stylus pointers.

* @function Pointers.setLockEndUUID - * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. - * @param {Uuid} objectID The ID of the object to which to lock on. - * @param {boolean} isAvatar False for entities, true for avatars - * @param {Mat4} [offsetMat] The offset matrix to use if you do not want to lock on to the center of the object. + * @param {number} id - The ID of the pointer. + * @param {Uuid} targetID - The ID of the entity or avatar to lock the pointer on to. + * @param {boolean} isAvatar - true if the target is an avatar, false if it is an entity. + * @param {Mat4} [offset] - The offset of the target point from the center of the target item. If not specified, the + * pointer locks on to the center of the target item. */ Q_INVOKABLE void setLockEndUUID(unsigned int uid, const QUuid& objectID, bool isAvatar, const glm::mat4& offsetMat = glm::mat4()) const { DependencyManager::get()->setLockEndUUID(uid, objectID, isAvatar, offsetMat); } /**jsdoc - * Check if a Pointer is associated with the left hand. + * Checks if a pointer is associated with the left hand: a ray or parabola pointer with joint property set to + * "_CONTROLLER_LEFTHAND" or "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", or a stylus pointer with + * hand property set to 0. * @function Pointers.isLeftHand - * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. - * @returns {boolean} True if the Pointer is a Joint Ray Pointer with joint == "_CONTROLLER_LEFTHAND" or "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", or a Stylus Pointer with hand == 0 + * @param {number} id - The ID of the pointer. + * @returns {boolean} true if the pointer is associated with the left hand, false if it isn't. */ Q_INVOKABLE bool isLeftHand(unsigned int uid) { return DependencyManager::get()->isLeftHand(uid); } /**jsdoc - * Check if a Pointer is associated with the right hand. + * Checks if a pointer is associated with the right hand: a ray or parabola pointer with joint property set to + * "_CONTROLLER_RIGHTHAND" or "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND", or a stylus pointer with + * hand property set to 1. * @function Pointers.isRightHand - * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. - * @returns {boolean} True if the Pointer is a Joint Ray Pointer with joint == "_CONTROLLER_RIGHTHAND" or "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND", or a Stylus Pointer with hand == 1 + * @param {number} id - The ID of the pointer. + * @returns {boolean} true if the pointer is associated with the right hand, false if it isn't. */ Q_INVOKABLE bool isRightHand(unsigned int uid) { return DependencyManager::get()->isRightHand(uid); } /**jsdoc - * Check if a Pointer is associated with the system mouse. + * Checks if a pointer is associated with the system mouse: a ray or parabola pointer with joint property set + * to "Mouse". * @function Pointers.isMouse - * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. - * @returns {boolean} True if the Pointer is a Mouse Ray Pointer, false otherwise. + * @param {number} id - The ID of the pointer. + * @returns {boolean} true if the pointer is associated with the system mouse, false if it isn't. */ Q_INVOKABLE bool isMouse(unsigned int uid) { return DependencyManager::get()->isMouse(uid); } /**jsdoc - * Returns information about an existing Pointer + * Gets information about a pointer. * @function Pointers.getPointerProperties - * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. - * @returns {Pointers.LaserPointerProperties|Pointers.StylusPointerProperties|Pointers.ParabolaPointerProperties} The information about the Pointer. - * Currently only includes renderStates and defaultRenderStates with associated entity IDs. + * @param {number} id - The ID of the pointer. + * @returns {Pointers.RayPointerProperties|Pointers.ParabolaPointerProperties|{}} The renderStates and + * defaultRenderStates for ray and parabola pointers, {} for stylus pointers. + * @example Report the properties of a parabola pointer. + * var intersectEnd = { + * type: "sphere", + * dimensions: { x: 0.2, y: 0.2, z: 0.2 }, + * solid: true, + * color: { red: 0, green: 255, blue: 0 }, + * ignorePickIntersection: true + * }; + * var intersectedPath = { + * color: { red: 0, green: 255, blue: 0 }, + * }; + * var searchEnd = { + * type: "sphere", + * dimensions: { x: 0.2, y: 0.2, z: 0.2 }, + * solid: true, + * color: { red: 255, green: 0, blue: 0 }, + * ignorePickIntersection: true + * }; + * var searchPath = { + * color: { red: 255, green: 0, blue: 0 }, + * }; + * + * var renderStates = [{ name: "example", path: intersectedPath, end: intersectEnd }]; + * var defaultRenderStates = [{ name: "example", distance: 20.0, path: searchPath, end: searchEnd }]; + * + * // Create the pointer. + * var parabolaPointer = Pointers.createPointer(PickType.Parabola, { + * joint: "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", + * filter: Picks.PICK_LOCAL_ENTITIES | Picks.PICK_DOMAIN_ENTITIES | Picks.PICK_INCLUDE_NONCOLLIDABLE, + * renderStates: renderStates, + * defaultRenderStates: defaultRenderStates, + * enabled: true + * }); + * Pointers.setRenderState(parabolaPointer, "example"); + * + * // Report the pointer properties. + * Script.setTimeout(function () { + * var properties = Pointers.getPointerProperties(parabolaPointer); + * print("Pointer properties:" + JSON.stringify(properties)); + * }, 500); + * + * // Tidy up. + * Script.scriptEnding.connect(function () { + * Pointers.removePointer(parabolaPointer); + * }); */ Q_INVOKABLE QVariantMap getPointerProperties(unsigned int uid) const; }; From e109c8f6d310356d678d85ea3f4ebf2b1cb7a180 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 2 Jul 2019 08:13:12 +1200 Subject: [PATCH 03/30] Picks and RayPick API JSdoc updates per Pointers API JSDoc --- .../src/raypick/PickScriptingInterface.cpp | 8 +++--- .../src/raypick/PickScriptingInterface.h | 25 +++++++++++-------- .../src/raypick/RayPickScriptingInterface.h | 23 +++++++++-------- 3 files changed, 31 insertions(+), 25 deletions(-) diff --git a/interface/src/raypick/PickScriptingInterface.cpp b/interface/src/raypick/PickScriptingInterface.cpp index 82d00d803f..c01455a3e3 100644 --- a/interface/src/raypick/PickScriptingInterface.cpp +++ b/interface/src/raypick/PickScriptingInterface.cpp @@ -55,7 +55,7 @@ PickFilter getPickFilter(unsigned int filter) { } /**jsdoc - * A set of properties that can be passed to {@link Picks.createPick} when creating a new ray pick. + * The properties of a ray pick. * * @typedef {object} Picks.RayPickProperties * @property {boolean} [enabled=false] - true if this pick should start enabled, false if it should @@ -138,7 +138,7 @@ unsigned int PickScriptingInterface::createRayPick(const QVariant& properties) { } /**jsdoc - * A set of properties that can be passed to {@link Picks.createPick} when creating a new stylus pick. + * The properties of a stylus pick. * * @typedef {object} Picks.StylusPickProperties * @property {number} [hand=-1] 0 for the left hand, 1 for the right hand, invalid (-1) @@ -189,7 +189,7 @@ unsigned int PickScriptingInterface::createStylusPick(const QVariant& properties // NOTE: Laser pointer still uses scaleWithAvatar. Until scaleWithAvatar is also deprecated for pointers, scaleWithAvatar should not be removed from the pick API. /**jsdoc - * A set of properties that can be passed to {@link Picks.createPick} when creating a new parabola pick. + * The properties of a parabola pick. * * @typedef {object} Picks.ParabolaPickProperties * @property {boolean} [enabled=false] - true if this pick should start enabled, false if it should @@ -297,7 +297,7 @@ unsigned int PickScriptingInterface::createParabolaPick(const QVariant& properti /**jsdoc - * A set of properties that can be passed to {@link Picks.createPick} when creating a new collision pick. + * The properties or a collision pick. * * @typedef {object} Picks.CollisionPickProperties * @property {boolean} [enabled=false] - true if this pick should start enabled, false if it should diff --git a/interface/src/raypick/PickScriptingInterface.h b/interface/src/raypick/PickScriptingInterface.h index 1cbdaa92f7..e973ee3643 100644 --- a/interface/src/raypick/PickScriptingInterface.h +++ b/interface/src/raypick/PickScriptingInterface.h @@ -194,7 +194,8 @@ public: Q_INVOKABLE QVariantMap getPrevPickResult(unsigned int uid); /**jsdoc - * Sets whether or not to use precision picking, i.e., whether to pick against precise meshes or coarse meshes. + * Sets whether or not a pick should use precision picking, i.e., whether it should pick against precise meshes or coarse + * meshes. * This has the same effect as using the PICK_PRECISE or PICK_COARSE filter flags. * @function Picks.setPrecisionPicking * @param {number} id - The ID of the pick. @@ -203,7 +204,7 @@ public: Q_INVOKABLE void setPrecisionPicking(unsigned int uid, bool precisionPicking); /**jsdoc - * Sets a list of entity and avatar IDs to ignore during intersection. + * Sets a list of entity and avatar IDs that a pick should ignore during intersection. *

Note: Not used by stylus picks.

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

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

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

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

* @function Picks.setIncludeItems * @param {number} id - The ID of the pick. * @param {Uuid[]} includeItems - The list of IDs to include. @@ -221,9 +223,9 @@ public: Q_INVOKABLE void setIncludeItems(unsigned int uid, const QScriptValue& includeItems); /**jsdoc - * Checks if a pick is associated with the left hand: a ray or parabola pick with joint set to - * "_CONTROLLER_LEFTHAND" or "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", or a stylus pick with hand - * set to 0. + * Checks if a pick is associated with the left hand: a ray or parabola pick with joint property set to + * "_CONTROLLER_LEFTHAND" or "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", or a stylus pick with + * hand property set to 0. * @function Picks.isLeftHand * @param {number} id - The ID of the pick. * @returns {boolean} true if the pick is associated with the left hand, false if it isn't. @@ -231,9 +233,9 @@ public: Q_INVOKABLE bool isLeftHand(unsigned int uid); /**jsdoc - * Checks if a pick is associated with the right hand: a ray or parabola pick with joint set to - * "_CONTROLLER_RIGHTHAND" or "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND", or a stylus pick with hand - * set to 1. + * Checks if a pick is associated with the right hand: a ray or parabola pick with joint property set to + * "_CONTROLLER_RIGHTHAND" or "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND", or a stylus pick with + * hand property set to 1. * @function Picks.isRightHand * @param {number} id - The ID of the pick. * @returns {boolean} true if the pick is associated with the right hand, false if it isn't. @@ -241,7 +243,8 @@ public: Q_INVOKABLE bool isRightHand(unsigned int uid); /**jsdoc - * Checks if a pick is associated with the system mouse: a ray or parabola pick with joint set to "Mouse". + * Checks if a pick is associated with the system mouse: a ray or parabola pick with joint property set to + * "Mouse". * @function Picks.isMouse * @param {number} id - The ID of the pick. * @returns {boolean} true if the pick is associated with the system mouse, false if it isn't. diff --git a/interface/src/raypick/RayPickScriptingInterface.h b/interface/src/raypick/RayPickScriptingInterface.h index 32a2ec4a5d..2a00847510 100644 --- a/interface/src/raypick/RayPickScriptingInterface.h +++ b/interface/src/raypick/RayPickScriptingInterface.h @@ -107,7 +107,8 @@ public: /**jsdoc - * Sets whether or not to use precision picking, i.e., whether to pick against precise meshes or coarse meshes. + * Sets whether or not a ray pick should use precision picking, i.e., whether it should pick against precise meshes or + * coarse meshes. * @function RayPick.setPrecisionPicking * @param {number} id - The ID of the ray pick. * @param {boolean} precisionPicking - true to use precision picking, false to use coarse picking. @@ -115,7 +116,7 @@ public: Q_INVOKABLE void setPrecisionPicking(unsigned int uid, bool precisionPicking); /**jsdoc - * Sets a list of entity and avatar IDs to ignore during intersection. + * Sets a list of entity and avatar IDs that a ray pick should ignore during intersection. * @function RayPick.setIgnoreItems * @param {number} id - The ID of the ray pick. * @param {Uuid[]} ignoreItems - The list of IDs to ignore. @@ -123,7 +124,8 @@ public: Q_INVOKABLE void setIgnoreItems(unsigned int uid, const QScriptValue& ignoreEntities); /**jsdoc - * Sets a list of entity IDs and/or avatar IDs to include during intersection, instead of intersecting with everything. + * Sets a list of entity and avatar IDs that a ray pick should include during intersection, instead of intersecting with + * everything. * @function RayPick.setIncludeItems * @param {number} id - The ID of the ray pick. * @param {Uuid[]} includeItems - The list of IDs to include. @@ -132,9 +134,9 @@ public: /**jsdoc - * Checks if a pick is associated with the left hand: a ray or parabola pick with joint set to - * "_CONTROLLER_LEFTHAND" or "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", or a stylus pick with hand - * set to 0. + * Checks if a pick is associated with the left hand: a ray or parabola pick with joint property set to + * "_CONTROLLER_LEFTHAND" or "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", or a stylus pick with + * hand property set to 0. * @function RayPick.isLeftHand * @param {number} id - The ID of the ray pick. * @returns {boolean} true if the pick is associated with the left hand, false if it isn't. @@ -142,9 +144,9 @@ public: Q_INVOKABLE bool isLeftHand(unsigned int uid); /**jsdoc - * Checks if a pick is associated with the right hand: a ray or parabola pick with joint set to - * "_CONTROLLER_RIGHTHAND" or "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND", or a stylus pick with hand - * set to 1. + * Checks if a pick is associated with the right hand: a ray or parabola pick with joint property set to + * "_CONTROLLER_RIGHTHAND" or "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND", or a stylus pick with + * hand property set to 1. * @function RayPick.isRightHand * @param {number} id - The ID of the ray pick. * @returns {boolean} true if the pick is associated with the right hand, false if it isn't. @@ -152,7 +154,8 @@ public: Q_INVOKABLE bool isRightHand(unsigned int uid); /**jsdoc - * Checks if a pick is associated with the system mouse: a ray or parabola pick with joint set to "Mouse". + * Checks if a pick is associated with the system mouse: a ray or parabola pick with joint property set to + * "Mouse". * @function RayPick.isMouse * @param {number} id - The ID of the ray pick. * @returns {boolean} true if the pick is associated with the system mouse, false if it isn't. From b7e92e099410e079c0bfcca882255737ace98f27 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 2 Jul 2019 16:02:33 +1200 Subject: [PATCH 04/30] LaserPointers API JSDoc update --- .../raypick/LaserPointerScriptingInterface.h | 113 +++++++++++------- 1 file changed, 69 insertions(+), 44 deletions(-) diff --git a/interface/src/raypick/LaserPointerScriptingInterface.h b/interface/src/raypick/LaserPointerScriptingInterface.h index 425ffd7de4..6c5ce0dbaf 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.h +++ b/interface/src/raypick/LaserPointerScriptingInterface.h @@ -21,121 +21,146 @@ class LaserPointerScriptingInterface : public QObject, public Dependency { SINGLETON_DEPENDENCY /**jsdoc - * Synonym for {@link Pointers} as used for laser pointers. Deprecated. + * The LaserPointers API is a subset of the {@link Pointers} API. It lets you create, manage, and visually + * represent objects for repeatedly calculating ray intersections with avatars, entities, and overlays. Ray pointers can also + * be configured to generate events on entities and overlays intersected. + * + *

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

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

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

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

+ *

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

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

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

+ *
    + *
  • The name of one of the render states set in the pointer's properties.
  • + *
  • "", to hide the pointer and disable emitting of events.
  • + *
+ * @param {number} id - The ID of the pointer. */ Q_INVOKABLE void setRenderState(unsigned int uid, const QString& renderState) const { DependencyManager::get()->setRenderState(uid, renderState.toStdString()); } /**jsdoc + * Gets the most recent intersection of a pointer. A pointer continues to be updated ready to return a result, as long as + * it is enabled, regardless of the render state. * @function LaserPointers.getPrevRayPickResult - * @param {number} id - * @returns {RayPickResult} + * @param {number} id - The ID of the pointer. + * @returns {RayPickResult} The most recent intersection of the pointer. */ Q_INVOKABLE QVariantMap getPrevRayPickResult(unsigned int uid) const; - - /**jsdoc - * @function LaserPointers.setPrecisionPicking - * @param {number} id - * @param {boolean} precisionPicking - */ + // jsdoc @borrows from Pointers Q_INVOKABLE void setPrecisionPicking(unsigned int uid, bool precisionPicking) const { DependencyManager::get()->setPrecisionPicking(uid, precisionPicking); } /**jsdoc + * Sets the length of a pointer. * @function LaserPointers.setLaserLength - * @param {number} id - * @param {number} laserLength + * @param {number} id - The ID of the pointer. + * @param {number} laserLength - The desired length of the pointer. */ Q_INVOKABLE void setLaserLength(unsigned int uid, float laserLength) const { DependencyManager::get()->setLength(uid, laserLength); } /**jsdoc + * Sets a list of entity and avatar IDs that a pointer should ignore during intersection. * @function LaserPointers.setIgnoreItems - * @param {number} id - * @param {Uuid[]} ignoreItems + * @param {number} id - The ID of the pointer. + * @param {Uuid[]} ignoreItems - A list of IDs to ignore. */ Q_INVOKABLE void setIgnoreItems(unsigned int uid, const QScriptValue& ignoreEntities) const; /**jsdoc + * Sets a list of entity and avatar IDs that a pointer should include during intersection, instead of intersecting with + * everything. * @function LaserPointers.setIncludeItems - * @param {number} id - * @param {Uuid[]} includeItems + * @param {number} id - The ID of the pointer. + * @param {Uuid[]} includeItems - A list of IDs to include. */ Q_INVOKABLE void setIncludeItems(unsigned int uid, const QScriptValue& includeEntities) const; /**jsdoc + * Locks a pointer onto a specific entity or avatar. * @function LaserPointers.setLockEndUUID - * @param {number} id - * @param {Uuid} itemID - * @param {boolean} isAvatar - * @param {Mat4} [offsetMat] + * @param {number} id - The ID of the pointer. + * @param {Uuid} targetID - The ID of the entity or avatar to lock the pointer on to. + * @param {boolean} isAvatar - true if the target is an avatar, false if it is an entity. + * @param {Mat4} [offset] - The offset of the target point from the center of the target item. If not specified, the + * pointer locks on to the center of the target item. */ Q_INVOKABLE void setLockEndUUID(unsigned int uid, const QUuid& objectID, bool isAvatar, const glm::mat4& offsetMat = glm::mat4()) const { DependencyManager::get()->setLockEndUUID(uid, objectID, isAvatar, offsetMat); } /**jsdoc + * Checks if a pointer is associated with the left hand: a pointer with joint property set to + * "_CONTROLLER_LEFTHAND" or "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND". * @function LaserPointers.isLeftHand - * @param {number} id - * @returns {boolean} + * @param {number} id - The ID of the pointer. + * @returns {boolean} true if the pointer is associated with the left hand, false if it isn't. */ Q_INVOKABLE bool isLeftHand(unsigned int uid) { return DependencyManager::get()->isLeftHand(uid); } /**jsdoc + * Checks if a pointer is associated with the right hand: a pointer with joint property set to + * "_CONTROLLER_RIGHTHAND" or "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND". * @function LaserPointers.isRightHand - * @param {number} id - * @returns {boolean} + * @param {number} id - The ID of the pointer. + * @returns {boolean} true if the pointer is associated with the right hand, false if it isn't. */ Q_INVOKABLE bool isRightHand(unsigned int uid) { return DependencyManager::get()->isRightHand(uid); } /**jsdoc + * Checks if a pointer is associated with the system mouse: a pointer with joint property set to + * "Mouse". * @function LaserPointers.isMouse - * @param {number} id - * @returns {boolean} + * @param {number} id - The ID of the pointer. + * @returns {boolean} true if the pointer is associated with the system mouse, false if it isn't. */ Q_INVOKABLE bool isMouse(unsigned int uid) { return DependencyManager::get()->isMouse(uid); } }; From c6fd726111953e484e7829e0f85fc20f44bffaaf Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 2 Jul 2019 16:07:39 +1200 Subject: [PATCH 05/30] Typos etc. --- interface/src/raypick/PointerScriptingInterface.cpp | 3 ++- interface/src/raypick/PointerScriptingInterface.h | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/interface/src/raypick/PointerScriptingInterface.cpp b/interface/src/raypick/PointerScriptingInterface.cpp index d904706b08..5bff7d4589 100644 --- a/interface/src/raypick/PointerScriptingInterface.cpp +++ b/interface/src/raypick/PointerScriptingInterface.cpp @@ -54,7 +54,8 @@ unsigned int PointerScriptingInterface::createPointer(const PickQuery::PickType& * The properties of a stylus pointer. These include the properties from the underlying stylus pick that the pointer uses. * @typedef {object} Pointers.StylusPointerProperties * @property {Pointers.StylusPointerModel} [model] - Override some or all of the default stylus model properties. - * @property {boolean} [hover=false] - If true, the pointer generates {@link Entities} hover events. + * @property {boolean} [hover=false] - true if the pointer generates {@link Entities} hover events, + * false if it doesn't. * @see {@link Picks.StylusPickProperties} for additional properties from the underlying stylus pick. */ /**jsdoc diff --git a/interface/src/raypick/PointerScriptingInterface.h b/interface/src/raypick/PointerScriptingInterface.h index 58959570ab..823767467e 100644 --- a/interface/src/raypick/PointerScriptingInterface.h +++ b/interface/src/raypick/PointerScriptingInterface.h @@ -53,7 +53,7 @@ public: */ /**jsdoc - * Creates a new ray, parabola, or stylus pointer. The pointers can have a wide range of behaviors depending on the + * Creates a new ray, parabola, or stylus pointer. The pointer can have a wide range of behaviors depending on the * properties specified. For example, a ray pointer may be a static ray pointer, a mouse ray pointer, or joint ray * pointer. *

Warning: Pointers created using this method currently always intersect at least visible and @@ -306,11 +306,11 @@ public: /**jsdoc - * Gets the most recent pick result from a pointer. A pointer continues to be updated ready to return a result, as long as + * 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} id - The ID of the pointer. - * @returns {RayPickResult|ParabolaPickResult|StylusPickResult} The most recent intersection result. + * @returns {RayPickResult|ParabolaPickResult|StylusPickResult} The most recent intersection of the pointer. */ Q_INVOKABLE QVariantMap getPrevPickResult(unsigned int uid) const; @@ -399,7 +399,7 @@ public: * Gets information about a pointer. * @function Pointers.getPointerProperties * @param {number} id - The ID of the pointer. - * @returns {Pointers.RayPointerProperties|Pointers.ParabolaPointerProperties|{}} The renderStates and + * @returns {Pointers.RayPointerProperties|Pointers.ParabolaPointerProperties|object} The renderStates and * defaultRenderStates for ray and parabola pointers, {} for stylus pointers. * @example Report the properties of a parabola pointer. * var intersectEnd = { From 5c29eb04b388748d5baaf2620b424d4be5d72757 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 2 Jul 2019 16:19:32 +1200 Subject: [PATCH 06/30] Typo --- interface/src/raypick/PickScriptingInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/raypick/PickScriptingInterface.cpp b/interface/src/raypick/PickScriptingInterface.cpp index c01455a3e3..12f68c1430 100644 --- a/interface/src/raypick/PickScriptingInterface.cpp +++ b/interface/src/raypick/PickScriptingInterface.cpp @@ -297,7 +297,7 @@ unsigned int PickScriptingInterface::createParabolaPick(const QVariant& properti /**jsdoc - * The properties or a collision pick. + * The properties of a collision pick. * * @typedef {object} Picks.CollisionPickProperties * @property {boolean} [enabled=false] - true if this pick should start enabled, false if it should From 2c412808e71696039e62b63aedde3bd06dc3480f Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 2 Jul 2019 14:48:25 +0200 Subject: [PATCH 07/30] More information from the platform on mac --- .../src/platform/backend/MACOSPlatform.cpp | 262 ++++++++++++++---- .../utilities/lib/prop/PropGroup.qml | 1 + .../utilities/render/performanceSetup.qml | 1 + 3 files changed, 211 insertions(+), 53 deletions(-) diff --git a/libraries/platform/src/platform/backend/MACOSPlatform.cpp b/libraries/platform/src/platform/backend/MACOSPlatform.cpp index cacbd06816..c510059093 100644 --- a/libraries/platform/src/platform/backend/MACOSPlatform.cpp +++ b/libraries/platform/src/platform/backend/MACOSPlatform.cpp @@ -19,6 +19,9 @@ #include #include +#include +#include + #include #include #include @@ -36,73 +39,226 @@ void MACOSInstance::enumerateCpus() { _cpus.push_back(cpu); } +#include + void MACOSInstance::enumerateGpus() { #ifdef Q_OS_MAC - - GPUIdent* ident = GPUIdent::getInstance(); - json gpu = {}; - - gpu[keys::gpu::model] = ident->getName().toUtf8().constData(); - gpu[keys::gpu::vendor] = findGPUVendorInDescription(gpu[keys::gpu::model].get()); - gpu[keys::gpu::videoMemory] = ident->getMemory(); - gpu[keys::gpu::driver] = ident->getDriver().toUtf8().constData(); - - _gpus.push_back(gpu); + // 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; + } + struct CGLRendererDesc { + int rendererID{0}; + int deviceVRAM{0}; + int majorGLVersion{0}; + int registryIDLow{0}; + int registryIDHigh{0}; + int displayMask{0}; + }; + std::vector renderers(rendererInfoCount); + + // 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++) { + auto& desc = renderers[i]; + + CGLDescribeRenderer(rendererInfo, i, kCGLRPRendererID, &desc.rendererID); + CGLDescribeRenderer(rendererInfo, i, kCGLRPVideoMemoryMegabytes, &desc.deviceVRAM); + CGLDescribeRenderer(rendererInfo, i, kCGLRPMajorGLVersion, &desc.majorGLVersion); + CGLDescribeRenderer(rendererInfo, i, kCGLRPRegistryIDLow, &desc.registryIDLow); + CGLDescribeRenderer(rendererInfo, i, kCGLRPRegistryIDHigh, &desc.registryIDHigh); + CGLDescribeRenderer(rendererInfo, i, kCGLRPDisplayMask, &desc.displayMask); + + kCGLRPDisplayMask + json gpu = {}; + gpu["A"] =desc.rendererID; + gpu["B"] =desc.deviceVRAM; + gpu["C"] =desc.majorGLVersion; + + gpu["D"] =desc.registryIDLow; + gpu["E"] =desc.registryIDHigh; + gpu["F"] =desc.displayMask; + + _gpus.push_back(gpu); + } + + CGLDestroyRendererInfo(rendererInfo); + + //get gpu / display information from the system profiler + + FILE* stream = popen("system_profiler SPDisplaysDataType | grep -e Chipset -e VRAM -e Vendor -e \"Device ID\" -e Displays -e \"Display Type\" -e Resolution -e \"Main Display\"", "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)) { + json gpu = {}; + gpu[keys::gpu::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 + gpu[keys::gpu::vendor] = findGPUVendorInDescription(gpu[keys::gpu::model].get()); + + // 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)) { + gpu[keys::gpu::videoMemory] = std::stoi(amount.str(1)) * GB_TO_MB; + } else if (std::regex_search(memAmountUnit, amount, memAmountMBToken)) { + gpu[keys::gpu::videoMemory] = std::stoi(amount.str(1)); + } else { + gpu[keys::gpu::videoMemory] = found.str(2); + } + } + + // Find the Device ID + const std::regex deviceIDToken("(Device ID: )(.*)"); + if (std::regex_search(gpuDesc, found, deviceIDToken)) { + gpu["deviceID"] = std::stoi(found.str(2)); + } + + // Enumerate the Displays + const std::regex displaysToken("(Displays: )"); + if (std::regex_search(gpuDesc, found, displaysToken)) { + std::string displayArrayDesc = found.suffix(); + std::vector displays; + + int displayIndex = 0; + const std::regex displayTypeToken("(Display Type: )(.*)"); + while (std::regex_search(displayArrayDesc, found, displayTypeToken)) { + json display = {}; + display["display"] = found.str(2); + + // Find the end of the display block + displayArrayDesc = found.suffix(); + std::string displayDesc = displayArrayDesc; + const std::regex endDisplayToken("Display Type: "); + if (std::regex_search(displayArrayDesc, found, endDisplayToken)) { + displayDesc = found.prefix(); + } + + // Find the resolution + const std::regex resolutionToken("(Resolution: )(.*)"); + if (std::regex_search(displayDesc, found, deviceIDToken)) { + display["resolution"] = found.str(2); + } + + // Find is main display + const std::regex mainMonitorToken("(Main Display: )(.*)"); + if (std::regex_search(displayDesc, found, mainMonitorToken)) { + display["isMaster"] = found.str(2); + } else { + display["isMaster"] = "false"; + } + + display["index"] = displayIndex; + displayIndex++; + + displays.push_back(display); + } + if (!displays.empty()) { + gpu["displays"] = displays; + } + } + + _gpus.push_back(gpu); + } #endif } void MACOSInstance::enumerateDisplays() { #ifdef Q_OS_MAC - auto displayID = CGMainDisplayID(); - auto displaySize = CGDisplayScreenSize(displayID); + uint32_t numDisplays = 0; + CGError error = CGGetOnlineDisplayList(0, nullptr, &numDisplays); + if (numDisplays <= 0 || error != kCGErrorSuccess) { + return; + } + + std::vector onlineDisplayIDs(numDisplays, 0); + error = CGGetOnlineDisplayList(onlineDisplayIDs.size(), onlineDisplayIDs.data(), &numDisplays); + if (error != kCGErrorSuccess) { + return; + } + + for (auto displayID : onlineDisplayIDs) { + 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); - - 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 glmask = CGDisplayIDToOpenGLDisplayMask(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); + + 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 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; + 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; + display["unit"] = displayUnit; + display["vendor"] = displayVendor; + display["model"] = displayModel; + display["serial"] = displaySerial; + + display["refreshrate"] =displayRefreshrate; + display["modeWidth"] = displayModeWidth; + display["modeHeight"] = displayModeHeight; + + display["glmask"] = glmask; - _displays.push_back(display); + _displays.push_back(display); + } #endif } diff --git a/scripts/developer/utilities/lib/prop/PropGroup.qml b/scripts/developer/utilities/lib/prop/PropGroup.qml index 848ff8b288..b1c65d04fd 100644 --- a/scripts/developer/utilities/lib/prop/PropGroup.qml +++ b/scripts/developer/utilities/lib/prop/PropGroup.qml @@ -98,6 +98,7 @@ PropFolderPanel { "label": itemLabel, "rootObject":itemRootObject, "indentDepth": itemDepth, + "isUnfold": true, }) } break; case 'printLabel': { diff --git a/scripts/developer/utilities/render/performanceSetup.qml b/scripts/developer/utilities/render/performanceSetup.qml index 4654736f72..be9b6a3271 100644 --- a/scripts/developer/utilities/render/performanceSetup.qml +++ b/scripts/developer/utilities/render/performanceSetup.qml @@ -51,6 +51,7 @@ Rectangle { } Prop.PropFolderPanel { label: "Platform" + isUnfold: true panelFrameData: Component { Platform { } From 4973563c20416266a1f0a3aa266dde1582fec049 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 2 Jul 2019 16:29:19 -0700 Subject: [PATCH 08/30] return entity load priority operator to proper state --- interface/src/octree/SafeLanding.cpp | 14 ++++++++------ interface/src/octree/SafeLanding.h | 6 ++++-- .../entities-renderer/src/EntityTreeRenderer.h | 1 + 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/interface/src/octree/SafeLanding.cpp b/interface/src/octree/SafeLanding.cpp index c358df746b..75e512232b 100644 --- a/interface/src/octree/SafeLanding.cpp +++ b/interface/src/octree/SafeLanding.cpp @@ -19,6 +19,11 @@ const int SafeLanding::SEQUENCE_MODULO = std::numeric_limits::max() + 1; +CalculateEntityLoadingPriority SafeLanding::entityLoadingOperatorElevateCollidables = [](const EntityItem& entityItem) { + const int COLLIDABLE_ENTITY_PRIORITY = 10.0f; + return entityItem.getCollisionless() * COLLIDABLE_ENTITY_PRIORITY; +}; + namespace { template bool lessThanWraparound(int a, int b) { constexpr int MAX_T_VALUE = std::numeric_limits::max(); @@ -52,7 +57,8 @@ void SafeLanding::startTracking(QSharedPointer entityTreeRen connect(std::const_pointer_cast(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(); diff --git a/interface/src/octree/SafeLanding.h b/interface/src/octree/SafeLanding.h index 2f1db2366f..87dac16ba3 100644 --- a/interface/src/octree/SafeLanding.h +++ b/interface/src/octree/SafeLanding.h @@ -20,6 +20,8 @@ #include "EntityItem.h" #include "EntityDynamicInterface.h" +#include "EntityTreeRenderer.h" + class EntityTreeRenderer; class EntityItemID; @@ -64,8 +66,8 @@ private: std::set _sequenceNumbers; - static float ElevatedPriority(const EntityItem& entityItem); - static float StandardPriority(const EntityItem&) { return 0.0f; } + static CalculateEntityLoadingPriority entityLoadingOperatorElevateCollidables; + CalculateEntityLoadingPriority _prevEntityLoadingPriorityOperator { nullptr }; static const int SEQUENCE_MODULO; }; diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index bea04f106b..b9fda690dd 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -69,6 +69,7 @@ public: virtual PacketType getExpectedPacketType() const override { return PacketType::EntityData; } // Returns the priority at which an entity should be loaded. Higher values indicate higher priority. + static CalculateEntityLoadingPriority getEntityLoadingPriorityOperator() { return _calculateEntityLoadingPriorityFunc; } static float getEntityLoadingPriority(const EntityItem& item) { return _calculateEntityLoadingPriorityFunc(item); } static void setEntityLoadingPriorityFunction(CalculateEntityLoadingPriority fn) { _calculateEntityLoadingPriorityFunc = fn; } From a1968bd9d0133fc1901938a0e6767fca051ab35a Mon Sep 17 00:00:00 2001 From: Samuel Gateau Date: Wed, 3 Jul 2019 01:00:52 -0700 Subject: [PATCH 09/30] Moving mac specific include at the correct place --- libraries/platform/src/platform/backend/MACOSPlatform.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/platform/src/platform/backend/MACOSPlatform.cpp b/libraries/platform/src/platform/backend/MACOSPlatform.cpp index c510059093..749b443257 100644 --- a/libraries/platform/src/platform/backend/MACOSPlatform.cpp +++ b/libraries/platform/src/platform/backend/MACOSPlatform.cpp @@ -25,6 +25,8 @@ #include #include #include + +#include #endif using namespace platform; @@ -39,7 +41,6 @@ void MACOSInstance::enumerateCpus() { _cpus.push_back(cpu); } -#include void MACOSInstance::enumerateGpus() { #ifdef Q_OS_MAC From 981311778ccfe9d8118632c242113d887285ba0e Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 3 Jul 2019 10:41:10 -0700 Subject: [PATCH 10/30] comments --- cmake/macros/AutoScribeShader.cmake | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cmake/macros/AutoScribeShader.cmake b/cmake/macros/AutoScribeShader.cmake index 9a18005424..f5a497962c 100755 --- a/cmake/macros/AutoScribeShader.cmake +++ b/cmake/macros/AutoScribeShader.cmake @@ -147,7 +147,12 @@ macro(AUTOSCRIBE_SHADER) 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) @@ -183,6 +188,7 @@ function(GENERATE_DEFINES_LIST_HELPER INPUT_LIST RETURN_LIST) 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}") @@ -301,6 +307,9 @@ macro(AUTOSCRIBE_SHADER_LIB) 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) From 1f54f3c159865045ccf77739923756a1340da288 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 3 Jul 2019 12:48:29 -0700 Subject: [PATCH 11/30] BUGZ-911: Place selected audio I/O information in About tab and in 'Copy to Clipboard' clipboard text --- .../simplifiedUI/settingsApp/about/About.qml | 73 ++++++++++++++++++- 1 file changed, 71 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/simplifiedUI/settingsApp/about/About.qml b/interface/resources/qml/hifi/simplifiedUI/settingsApp/about/About.qml index 3e3758e7a8..7fa9b63dab 100644 --- a/interface/resources/qml/hifi/simplifiedUI/settingsApp/about/About.qml +++ b/interface/resources/qml/hifi/simplifiedUI/settingsApp/about/About.qml @@ -47,8 +47,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 +195,73 @@ 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 + model: AudioScriptingInterface.devices.input + delegate: Item { + Component.onCompleted: { + if (HMD.active && selectedHMD) { + audioInputDevices.selectedInputDeviceName = model.devicename + } else if (!HMD.active && selectedDesktop) { + audioInputDevices.selectedInputDeviceName = model.devicename + } + } + } + } + + HifiStylesUit.GraphikRegular { + text: "Audio Input: " + audioInputDevices.selectedInputDeviceName + Layout.maximumWidth: parent.width + height: paintedHeight + size: 16 + color: simplifiedUI.colors.text.white + wrapMode: Text.Wrap + } + + + // This is a bit of a hack to get the name of the currently-selected audio output device + // in the current mode (Desktop or VR). The reason this is necessary is because it seems to me like + // the only way one can get a human-readable list of the audio I/O devices is by using a ListView + // and grabbing the names from the AudioScriptingInterface; you can't do it using a ListModel. + // See `AudioDevices.h`, specifically the comment above the declaration of `QVariant data()`. + ListView { + id: audioOutputDevices + visible: false + property string selectedOutputDeviceName + Layout.preferredWidth: parent.width + Layout.preferredHeight: contentItem.height + interactive: false + model: AudioScriptingInterface.devices.output + delegate: Item { + Component.onCompleted: { + if (HMD.active && selectedHMD) { + audioOutputDevices.selectedOutputDeviceName = model.devicename + } else if (!HMD.active && selectedDesktop) { + audioOutputDevices.selectedOutputDeviceName = model.devicename + } + } + } + } + + HifiStylesUit.GraphikRegular { + text: "Audio Output: " + audioOutputDevices.selectedOutputDeviceName + Layout.maximumWidth: parent.width + height: paintedHeight + size: 16 + color: simplifiedUI.colors.text.white + wrapMode: Text.Wrap + } + SimplifiedControls.Button { Layout.topMargin: 8 width: 200 @@ -248,6 +315,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); From dcbb0f5db55566d3d38e925e4776df7dded111e7 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Wed, 3 Jul 2019 15:22:41 -0700 Subject: [PATCH 12/30] Shut down interface when executing the Windows Launcher --- launchers/win32/LauncherApp.cpp | 5 +++++ launchers/win32/LauncherDlg.cpp | 6 ++++-- launchers/win32/LauncherManager.cpp | 17 +++++++++-------- launchers/win32/LauncherUtils.cpp | 15 ++++++++++++++- launchers/win32/LauncherUtils.h | 3 ++- 5 files changed, 34 insertions(+), 12 deletions(-) diff --git a/launchers/win32/LauncherApp.cpp b/launchers/win32/LauncherApp.cpp index 244d618fcb..a432a0b116 100644 --- a/launchers/win32/LauncherApp.cpp +++ b/launchers/win32/LauncherApp.cpp @@ -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; diff --git a/launchers/win32/LauncherDlg.cpp b/launchers/win32/LauncherDlg.cpp index 6016424563..83af659208 100644 --- a/launchers/win32/LauncherDlg.cpp +++ b/launchers/win32/LauncherDlg.cpp @@ -629,7 +629,8 @@ void CLauncherDlg::OnTimer(UINT_PTR nIDEvent) { ::SetForegroundWindow(_applicationWND); ::SetActiveWindow(_applicationWND); } - if (LauncherUtils::IsProcessRunning(L"interface.exe")) { + int interfacePID = -1; + if (LauncherUtils::IsProcessRunning(L"interface.exe", interfacePID)) { exit(0); } } @@ -653,7 +654,8 @@ void CLauncherDlg::OnTimer(UINT_PTR nIDEvent) { } _splashStep++; } else if (theApp._manager.shouldShutDown()) { - if (LauncherUtils::IsProcessRunning(L"interface.exe")) { + int interfacePID = -1; + if (LauncherUtils::IsProcessRunning(L"interface.exe", interfacePID)) { exit(0); } } diff --git a/launchers/win32/LauncherManager.cpp b/launchers/win32/LauncherManager.cpp index 2916f614cb..619ebe9c42 100644 --- a/launchers/win32/LauncherManager.cpp +++ b/launchers/win32/LauncherManager.cpp @@ -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); } @@ -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(); diff --git a/launchers/win32/LauncherUtils.cpp b/launchers/win32/LauncherUtils.cpp index 9365dd52a1..39964cc457 100644 --- a/launchers/win32/LauncherUtils.cpp +++ b/launchers/win32/LauncherUtils.cpp @@ -37,7 +37,19 @@ 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 LauncherUtils::IsProcessRunning(const wchar_t *processName, int& processID) { bool exists = false; PROCESSENTRY32 entry; entry.dwSize = sizeof(PROCESSENTRY32); @@ -48,6 +60,7 @@ BOOL LauncherUtils::IsProcessRunning(const wchar_t *processName) { while (Process32Next(snapshot, &entry)) { if (!_wcsicmp(entry.szExeFile, processName)) { exists = true; + processID = entry.th32ProcessID; break; } } diff --git a/launchers/win32/LauncherUtils.h b/launchers/win32/LauncherUtils.h index a6f124e18d..f5ce04b386 100644 --- a/launchers/win32/LauncherUtils.h +++ b/launchers/win32/LauncherUtils.h @@ -73,7 +73,8 @@ 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 IsProcessRunning(const wchar_t *processName, int& processID); + 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); From 597477614c9569d5a18f3fab4bd9f88c193296cc Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Wed, 3 Jul 2019 17:51:05 -0700 Subject: [PATCH 13/30] Debugging for missing Avatar Data --- assignment-client/src/avatars/AvatarMixerSlave.cpp | 7 +++++++ libraries/avatars/src/AvatarHashMap.cpp | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index 64f4aa6821..d874100ca2 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -453,6 +453,13 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node) // or that somehow we haven't sent if (lastSeqToReceiver == lastSeqFromSender && lastSeqToReceiver != 0) { ++numAvatarsHeldBack; + + // BUGZ-781 verbose debugging: + auto usecLastTimeSent = destinationNodeData->getLastOtherAvatarEncodeTime(sourceAvatarNodeData->getNodeLocalID()); + if (usecLastTimeSent != 0 && startIgnoreCalculation - usecLastTimeSent > 10 * USECS_PER_SECOND) { + qCDebug(avatars) << "Not sent avatar" << *sourceAvatarNode << "to Node" << *destinationNode << "in > 10 s"; + } + sendAvatar = false; } else if (lastSeqFromSender == 0) { // We have have not yet received any data about this avatar. Ignore it for now diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index cb14d7ef41..0c7054424f 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -280,6 +280,10 @@ AvatarSharedPointer AvatarHashMap::parseAvatarData(QSharedPointer, "Secondary", and "Tertiary" cause {@link Entities} and From 8284c8d015d7bed862bd14dfd24c0a90cf0ecbd7 Mon Sep 17 00:00:00 2001 From: Samuel Gateau Date: Thu, 4 Jul 2019 01:55:48 -0700 Subject: [PATCH 16/30] doing the full enumeration in windows --- .../platform/src/platform/PlatformKeys.h | 2 + .../src/platform/backend/Platform.cpp | 2 + .../src/platform/backend/PlatformInstance.cpp | 2 + .../src/platform/backend/WINPlatform.cpp | 104 +++++++++++++++++- 4 files changed, 109 insertions(+), 1 deletion(-) diff --git a/libraries/platform/src/platform/PlatformKeys.h b/libraries/platform/src/platform/PlatformKeys.h index e6c255ce75..bb71e88f94 100644 --- a/libraries/platform/src/platform/PlatformKeys.h +++ b/libraries/platform/src/platform/PlatformKeys.h @@ -30,6 +30,7 @@ namespace platform { namespace keys{ extern const char* model; extern const char* videoMemory; extern const char* driver; + extern const char* displays; } namespace nic { extern const char* mac; @@ -42,6 +43,7 @@ namespace platform { namespace keys{ extern const char* coordsRight; extern const char* coordsTop; extern const char* coordsBottom; + extern const char* gpu; } namespace memory { extern const char* memTotal; diff --git a/libraries/platform/src/platform/backend/Platform.cpp b/libraries/platform/src/platform/backend/Platform.cpp index 9284e0b3a0..a8c0f1b111 100644 --- a/libraries/platform/src/platform/backend/Platform.cpp +++ b/libraries/platform/src/platform/backend/Platform.cpp @@ -31,6 +31,7 @@ namespace platform { namespace keys { const char* model = "model"; const char* videoMemory = "videoMemory"; const char* driver = "driver"; + const char* displays = "displays"; } namespace nic { const char* mac = "mac"; @@ -43,6 +44,7 @@ namespace platform { namespace keys { const char* coordsRight = "coordinatesright"; const char* coordsTop = "coordinatestop"; const char* coordsBottom = "coordinatesbottom"; + const char* gpu = "gpu"; } namespace memory { const char* memTotal = "memTotal"; diff --git a/libraries/platform/src/platform/backend/PlatformInstance.cpp b/libraries/platform/src/platform/backend/PlatformInstance.cpp index 33b19cd012..69825cbfa5 100644 --- a/libraries/platform/src/platform/backend/PlatformInstance.cpp +++ b/libraries/platform/src/platform/backend/PlatformInstance.cpp @@ -98,6 +98,7 @@ json Instance::listAllKeys() { keys::gpu::model, keys::gpu::videoMemory, keys::gpu::driver, + keys::gpu::displays, keys::display::description, keys::display::name, @@ -105,6 +106,7 @@ json Instance::listAllKeys() { keys::display::coordsRight, keys::display::coordsTop, keys::display::coordsBottom, + keys::display::gpu, keys::memory::memTotal, diff --git a/libraries/platform/src/platform/backend/WINPlatform.cpp b/libraries/platform/src/platform/backend/WINPlatform.cpp index d07bb83510..0c09ae2de6 100644 --- a/libraries/platform/src/platform/backend/WINPlatform.cpp +++ b/libraries/platform/src/platform/backend/WINPlatform.cpp @@ -19,6 +19,8 @@ #include #include #include +#include +#pragma comment(lib, "dxgi.lib") #endif using namespace platform; @@ -34,6 +36,106 @@ void WINInstance::enumerateCpus() { } void WINInstance::enumerateGpus() { +#ifdef Q_OS_WIN + struct ConvertLargeIntegerToQString { + QString convert(const LARGE_INTEGER& version) { + QString value; + value.append(QString::number(uint32_t(((version.HighPart & 0xFFFF0000) >> 16) & 0x0000FFFF))); + value.append("."); + value.append(QString::number(uint32_t((version.HighPart) & 0x0000FFFF))); + value.append("."); + value.append(QString::number(uint32_t(((version.LowPart & 0xFFFF0000) >> 16) & 0x0000FFFF))); + value.append("."); + value.append(QString::number(uint32_t((version.LowPart) & 0x0000FFFF))); + return value; + } + } convertDriverVersionToString; + + // Create the DXGI factory + // Let s get into DXGI land: + HRESULT hr = S_OK; + + IDXGIFactory1* pFactory = nullptr; + hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)(&pFactory)); + if (hr != S_OK || pFactory == nullptr) { +// qCDebug(shared) << "Unable to create DXGI"; + return; + } + + std::vector validAdapterList; + using AdapterEntry = std::pair, std::vector>; + std::vector adapterToOutputs; + // Enumerate adapters and outputs + { + UINT adapterNum = 0; + IDXGIAdapter1* pAdapter = nullptr; + while (pFactory->EnumAdapters1(adapterNum, &pAdapter) != DXGI_ERROR_NOT_FOUND) { + // Found an adapter, get descriptor + DXGI_ADAPTER_DESC1 adapterDesc; + pAdapter->GetDesc1(&adapterDesc); + + LARGE_INTEGER version; + hr = pAdapter->CheckInterfaceSupport(__uuidof(IDXGIDevice), &version); + + std::wstring wDescription(adapterDesc.Description); + std::string description(wDescription.begin(), wDescription.end()); + + json gpu = {}; + gpu[keys::gpu::model] = description; + gpu[keys::gpu::vendor] = findGPUVendorInDescription(gpu[keys::gpu::model].get()); + const SIZE_T BYTES_PER_MEGABYTE = 1024 * 1024; + gpu[keys::gpu::videoMemory] = (uint32_t)(adapterDesc.DedicatedVideoMemory / BYTES_PER_MEGABYTE); + gpu[keys::gpu::driver] = convertDriverVersionToString.convert(version).toStdString(); + + + std::vector displayIndices; + + UINT outputNum = 0; + IDXGIOutput* pOutput; + bool hasOutputConnectedToDesktop = false; + while (pAdapter->EnumOutputs(outputNum, &pOutput) != DXGI_ERROR_NOT_FOUND) { + // FOund an output attached to the adapter, get descriptor + DXGI_OUTPUT_DESC outputDesc; + pOutput->GetDesc(&outputDesc); + + // Grab the Monitor desc + // MONITOR_DESC + + json display = {}; + + // Desiplay 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::coordsLeft] = outputDesc.DesktopCoordinates.left; + display[keys::display::coordsRight] = outputDesc.DesktopCoordinates.right; + display[keys::display::coordsBottom] = outputDesc.DesktopCoordinates.bottom; + display[keys::display::coordsTop] = outputDesc.DesktopCoordinates.top; + + // Add the display index to the list of displays of the gpu + displayIndices.push_back(_displays.size()); + + // And set the gpu index to the display description + display[keys::display::gpu] = _gpus.size(); + + // One more display desc + _displays.push_back(display); + pOutput->Release(); + outputNum++; + } + gpu[keys::gpu::displays] = displayIndices; + + _gpus.push_back(gpu); + pAdapter->Release(); + adapterNum++; + } + } + pFactory->Release(); +#endif GPUIdent* ident = GPUIdent::getInstance(); @@ -44,7 +146,7 @@ void WINInstance::enumerateGpus() { gpu[keys::gpu::driver] = ident->getDriver().toUtf8().constData(); _gpus.push_back(gpu); - _displays = ident->getOutput(); + // _displays = ident->getOutput(); } void WINInstance::enumerateMemory() { From 28fddc2fb350024a1f160936dcd4d89501e7887a Mon Sep 17 00:00:00 2001 From: Samuel Gateau Date: Thu, 4 Jul 2019 18:13:08 +0200 Subject: [PATCH 17/30] full stack for windows --- .../platform/src/platform/PlatformKeys.h | 8 +- .../src/platform/backend/AndroidPlatform.cpp | 3 +- .../src/platform/backend/AndroidPlatform.h | 2 +- .../src/platform/backend/LinuxPlatform.cpp | 5 +- .../src/platform/backend/LinuxPlatform.h | 2 +- .../src/platform/backend/MACOSPlatform.cpp | 20 ++-- .../src/platform/backend/MACOSPlatform.h | 3 +- .../src/platform/backend/Platform.cpp | 8 +- .../src/platform/backend/PlatformInstance.cpp | 11 +- .../src/platform/backend/PlatformInstance.h | 3 +- .../src/platform/backend/WINPlatform.cpp | 107 +++++++++++------- .../src/platform/backend/WINPlatform.h | 2 +- .../utilities/lib/prop/PropGroup.qml | 38 ++++--- 13 files changed, 118 insertions(+), 94 deletions(-) diff --git a/libraries/platform/src/platform/PlatformKeys.h b/libraries/platform/src/platform/PlatformKeys.h index bb71e88f94..ad9ae8e6e2 100644 --- a/libraries/platform/src/platform/PlatformKeys.h +++ b/libraries/platform/src/platform/PlatformKeys.h @@ -39,10 +39,10 @@ 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; } namespace memory { diff --git a/libraries/platform/src/platform/backend/AndroidPlatform.cpp b/libraries/platform/src/platform/backend/AndroidPlatform.cpp index b0a4c5e67b..4487d305cf 100644 --- a/libraries/platform/src/platform/backend/AndroidPlatform.cpp +++ b/libraries/platform/src/platform/backend/AndroidPlatform.cpp @@ -10,6 +10,7 @@ #include "../PlatformKeys.h" #include #include +#include using namespace platform; @@ -23,7 +24,7 @@ void AndroidInstance::enumerateCpus() { _cpus.push_back(cpu); } -void AndroidInstance::enumerateGpus() { +void AndroidInstance::enumerateGpusAndDisplays() { GPUIdent* ident = GPUIdent::getInstance(); json gpu = {}; gpu[keys::gpu::model] = ident->getName().toUtf8().constData(); diff --git a/libraries/platform/src/platform/backend/AndroidPlatform.h b/libraries/platform/src/platform/backend/AndroidPlatform.h index 6592b3519d..488f564057 100644 --- a/libraries/platform/src/platform/backend/AndroidPlatform.h +++ b/libraries/platform/src/platform/backend/AndroidPlatform.h @@ -16,7 +16,7 @@ namespace platform { public: void enumerateCpus() override; - void enumerateGpus() override; + void enumerateGpusAndDisplays() override; void enumerateMemory() override; void enumerateComputer() override; }; diff --git a/libraries/platform/src/platform/backend/LinuxPlatform.cpp b/libraries/platform/src/platform/backend/LinuxPlatform.cpp index 61501669cb..eb2c8d4259 100644 --- a/libraries/platform/src/platform/backend/LinuxPlatform.cpp +++ b/libraries/platform/src/platform/backend/LinuxPlatform.cpp @@ -12,6 +12,9 @@ #include #include #include + +#include + #include #include @@ -27,7 +30,7 @@ void LinuxInstance::enumerateCpus() { _cpus.push_back(cpu); } -void LinuxInstance::enumerateGpus() { +void LinuxInstance::enumerateGpusAndDisplays() { GPUIdent* ident = GPUIdent::getInstance(); json gpu = {}; gpu[keys::gpu::model] = ident->getName().toUtf8().constData(); diff --git a/libraries/platform/src/platform/backend/LinuxPlatform.h b/libraries/platform/src/platform/backend/LinuxPlatform.h index 2f2529db7c..0d2e567e0b 100644 --- a/libraries/platform/src/platform/backend/LinuxPlatform.h +++ b/libraries/platform/src/platform/backend/LinuxPlatform.h @@ -16,7 +16,7 @@ namespace platform { public: void enumerateCpus() override; - void enumerateGpus() override; + void enumerateGpusAndDisplays() override; void enumerateMemory() override; void enumerateComputer() override; }; diff --git a/libraries/platform/src/platform/backend/MACOSPlatform.cpp b/libraries/platform/src/platform/backend/MACOSPlatform.cpp index 749b443257..656a412268 100644 --- a/libraries/platform/src/platform/backend/MACOSPlatform.cpp +++ b/libraries/platform/src/platform/backend/MACOSPlatform.cpp @@ -12,7 +12,8 @@ #include #include #include -#include + +#include #ifdef Q_OS_MAC #include @@ -42,7 +43,7 @@ void MACOSInstance::enumerateCpus() { } -void MACOSInstance::enumerateGpus() { +void MACOSInstance::enumerateGpusAndDisplays() { #ifdef Q_OS_MAC // Collect Renderer info as exposed by the CGL layers GLuint cglDisplayMask = -1; // Iterate over all of them. @@ -191,9 +192,6 @@ void MACOSInstance::enumerateGpus() { } #endif -} - -void MACOSInstance::enumerateDisplays() { #ifdef Q_OS_MAC uint32_t numDisplays = 0; CGError error = CGGetOnlineDisplayList(0, nullptr, &numDisplays); @@ -240,10 +238,10 @@ void MACOSInstance::enumerateDisplays() { 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[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; display["isMaster"] = displayMaster; @@ -289,11 +287,11 @@ void MACOSInstance::enumerateComputer(){ _computer[keys::computer::model]=std::string(model); free(model); - -#endif auto sysInfo = QSysInfo(); _computer[keys::computer::OSVersion] = sysInfo.kernelVersion().toStdString(); +#endif + } diff --git a/libraries/platform/src/platform/backend/MACOSPlatform.h b/libraries/platform/src/platform/backend/MACOSPlatform.h index e893dda739..f249dad001 100644 --- a/libraries/platform/src/platform/backend/MACOSPlatform.h +++ b/libraries/platform/src/platform/backend/MACOSPlatform.h @@ -16,8 +16,7 @@ namespace platform { public: void enumerateCpus() override; - void enumerateGpus() override; - void enumerateDisplays() override; + void enumerateGpusAndDisplays() override; void enumerateMemory() override; void enumerateComputer() override; }; diff --git a/libraries/platform/src/platform/backend/Platform.cpp b/libraries/platform/src/platform/backend/Platform.cpp index a8c0f1b111..79687d8ba0 100644 --- a/libraries/platform/src/platform/backend/Platform.cpp +++ b/libraries/platform/src/platform/backend/Platform.cpp @@ -40,10 +40,10 @@ 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"; } namespace memory { diff --git a/libraries/platform/src/platform/backend/PlatformInstance.cpp b/libraries/platform/src/platform/backend/PlatformInstance.cpp index 69825cbfa5..4fd4a9aa2a 100644 --- a/libraries/platform/src/platform/backend/PlatformInstance.cpp +++ b/libraries/platform/src/platform/backend/PlatformInstance.cpp @@ -19,8 +19,7 @@ bool Instance::enumeratePlatform() { enumerateComputer(); enumerateMemory(); enumerateCpus(); - enumerateGpus(); - enumerateDisplays(); + enumerateGpusAndDisplays(); enumerateNics(); // And profile the platform and put the tier in "computer" @@ -102,10 +101,10 @@ json Instance::listAllKeys() { 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, diff --git a/libraries/platform/src/platform/backend/PlatformInstance.h b/libraries/platform/src/platform/backend/PlatformInstance.h index 6ceacaa3ff..e66aa94846 100644 --- a/libraries/platform/src/platform/backend/PlatformInstance.h +++ b/libraries/platform/src/platform/backend/PlatformInstance.h @@ -35,8 +35,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; diff --git a/libraries/platform/src/platform/backend/WINPlatform.cpp b/libraries/platform/src/platform/backend/WINPlatform.cpp index 0c09ae2de6..2f0210de16 100644 --- a/libraries/platform/src/platform/backend/WINPlatform.cpp +++ b/libraries/platform/src/platform/backend/WINPlatform.cpp @@ -11,23 +11,31 @@ #include #include + #include -#include + +#include #ifdef Q_OS_WIN +#include +#include +#include #include #include #include #include #include #pragma comment(lib, "dxgi.lib") +#include +#pragma comment(lib, "Shcore.lib") + #endif using namespace platform; void WINInstance::enumerateCpus() { json cpu = {}; - + cpu[keys::cpu::vendor] = CPUIdent::Vendor(); cpu[keys::cpu::model] = CPUIdent::Brand(); cpu[keys::cpu::numCores] = std::thread::hardware_concurrency(); @@ -35,19 +43,20 @@ void WINInstance::enumerateCpus() { _cpus.push_back(cpu); } -void WINInstance::enumerateGpus() { +void WINInstance::enumerateGpusAndDisplays() { #ifdef Q_OS_WIN - struct ConvertLargeIntegerToQString { - QString convert(const LARGE_INTEGER& version) { - QString value; - value.append(QString::number(uint32_t(((version.HighPart & 0xFFFF0000) >> 16) & 0x0000FFFF))); - value.append("."); - value.append(QString::number(uint32_t((version.HighPart) & 0x0000FFFF))); - value.append("."); - value.append(QString::number(uint32_t(((version.LowPart & 0xFFFF0000) >> 16) & 0x0000FFFF))); - value.append("."); - value.append(QString::number(uint32_t((version.LowPart) & 0x0000FFFF))); - return value; + 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; @@ -58,7 +67,6 @@ void WINInstance::enumerateGpus() { IDXGIFactory1* pFactory = nullptr; hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)(&pFactory)); if (hr != S_OK || pFactory == nullptr) { -// qCDebug(shared) << "Unable to create DXGI"; return; } @@ -85,8 +93,7 @@ void WINInstance::enumerateGpus() { gpu[keys::gpu::vendor] = findGPUVendorInDescription(gpu[keys::gpu::model].get()); const SIZE_T BYTES_PER_MEGABYTE = 1024 * 1024; gpu[keys::gpu::videoMemory] = (uint32_t)(adapterDesc.DedicatedVideoMemory / BYTES_PER_MEGABYTE); - gpu[keys::gpu::driver] = convertDriverVersionToString.convert(version).toStdString(); - + gpu[keys::gpu::driver] = convertDriverVersionToString.convert(version); std::vector displayIndices; @@ -98,12 +105,22 @@ void WINInstance::enumerateGpus() { DXGI_OUTPUT_DESC outputDesc; pOutput->GetDesc(&outputDesc); - // Grab the Monitor desc - // MONITOR_DESC + // 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); json display = {}; - // Desiplay name + // Display name std::wstring wDeviceName(outputDesc.DeviceName); std::string deviceName(wDeviceName.begin(), wDeviceName.end()); display[keys::display::name] = deviceName; @@ -111,14 +128,29 @@ void WINInstance::enumerateGpus() { // Rect region of the desktop in desktop units display["desktopRect"] = (outputDesc.AttachedToDesktop ? true : false); - display[keys::display::coordsLeft] = outputDesc.DesktopCoordinates.left; - display[keys::display::coordsRight] = outputDesc.DesktopCoordinates.right; - display[keys::display::coordsBottom] = outputDesc.DesktopCoordinates.bottom; - display[keys::display::coordsTop] = outputDesc.DesktopCoordinates.top; + 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; + + // DPI + display["ppiX"] = dpiX; + display["ppiY"] = dpiY; + display["physicalWidth"] = devMode.dmPelsWidth / (float) dpiX; + display["physicalHeight"] = devMode.dmPelsHeight / (float) dpiY; + display["modeWidth"] = devMode.dmPelsWidth; + display["modeHeight"] = devMode.dmPelsHeight; + + //Average the ppiX and Y scaled vs the the true ppi + display["ppi"] = 0.5f * (dpiX + dpiY); + display["desktopPPIScale"] = 0.5f * (dpiX / (float) dpiXScaled + dpiY / (float)dpiYScaled); + + // refreshrate + display["frequency"] = devMode.dmDisplayFrequency; // Add the display index to the list of displays of the gpu displayIndices.push_back(_displays.size()); - + // And set the gpu index to the display description display[keys::display::gpu] = _gpus.size(); @@ -136,22 +168,11 @@ void WINInstance::enumerateGpus() { } pFactory->Release(); #endif - - GPUIdent* ident = GPUIdent::getInstance(); - - json gpu = {}; - gpu[keys::gpu::model] = ident->getName().toUtf8().constData(); - gpu[keys::gpu::vendor] = findGPUVendorInDescription(gpu[keys::gpu::model].get()); - gpu[keys::gpu::videoMemory] = ident->getMemory(); - gpu[keys::gpu::driver] = ident->getDriver().toUtf8().constData(); - - _gpus.push_back(gpu); - // _displays = ident->getOutput(); } void WINInstance::enumerateMemory() { json ram = {}; - + #ifdef Q_OS_WIN MEMORYSTATUSEX statex; statex.dwLength = sizeof(statex); @@ -162,11 +183,11 @@ 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(); _computer[keys::computer::OSVersion] = sysInfo.kernelVersion().toStdString(); @@ -180,23 +201,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().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; diff --git a/libraries/platform/src/platform/backend/WINPlatform.h b/libraries/platform/src/platform/backend/WINPlatform.h index 4926d578f7..cc56ebfbbc 100644 --- a/libraries/platform/src/platform/backend/WINPlatform.h +++ b/libraries/platform/src/platform/backend/WINPlatform.h @@ -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; diff --git a/scripts/developer/utilities/lib/prop/PropGroup.qml b/scripts/developer/utilities/lib/prop/PropGroup.qml index b1c65d04fd..c6b2c694f6 100644 --- a/scripts/developer/utilities/lib/prop/PropGroup.qml +++ b/scripts/developer/utilities/lib/prop/PropGroup.qml @@ -86,20 +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, - "isUnfold": true, - }) } break; case 'printLabel': { var component = Qt.createComponent("PropItem.qml"); @@ -126,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 = {}; From 4cc3800384fd73a9f275426c114ba39992151f0a Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 5 Jul 2019 12:26:42 +0200 Subject: [PATCH 18/30] COmprehensive enumeration of gpu and displays from mac --- .../platform/src/platform/PlatformKeys.h | 10 + .../src/platform/backend/MACOSPlatform.cpp | 385 ++++++++++-------- .../src/platform/backend/Platform.cpp | 10 + .../src/platform/backend/WINPlatform.cpp | 37 +- 4 files changed, 248 insertions(+), 194 deletions(-) diff --git a/libraries/platform/src/platform/PlatformKeys.h b/libraries/platform/src/platform/PlatformKeys.h index ad9ae8e6e2..fceb3071a7 100644 --- a/libraries/platform/src/platform/PlatformKeys.h +++ b/libraries/platform/src/platform/PlatformKeys.h @@ -44,6 +44,16 @@ namespace platform { namespace keys{ extern const char* boundsTop; extern const char* boundsBottom; extern const char* gpu; + extern const char* ppiHorizontal; + extern const char* ppiVertical; + extern const char* ppi; + extern const char* physicalWidth; + extern const char* physicalHeight; + extern const char* modeRefreshrate; + extern const char* modeWidth; + extern const char* modeHeight; + extern const char* desktopPpi; + extern const char* isMaster; } namespace memory { extern const char* memTotal; diff --git a/libraries/platform/src/platform/backend/MACOSPlatform.cpp b/libraries/platform/src/platform/backend/MACOSPlatform.cpp index 656a412268..76ad16f019 100644 --- a/libraries/platform/src/platform/backend/MACOSPlatform.cpp +++ b/libraries/platform/src/platform/backend/MACOSPlatform.cpp @@ -26,7 +26,7 @@ #include #include #include - +#include #include #endif @@ -45,6 +45,90 @@ void MACOSInstance::enumerateCpus() { void MACOSInstance::enumerateGpusAndDisplays() { #ifdef Q_OS_MAC + // ennumerate the displays first + std::vector displayMasks; + { + uint32_t numDisplays = 0; + CGError error = CGGetOnlineDisplayList(0, nullptr, &numDisplays); + if (numDisplays <= 0 || error != kCGErrorSuccess) { + return; + } + + std::vector onlineDisplayIDs(numDisplays, 0); + error = CGGetOnlineDisplayList(onlineDisplayIDs.size(), onlineDisplayIDs.data(), &numDisplays); + if (error != kCGErrorSuccess) { + return; + } + + 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::ppiHorizontal] = ppiH; + display[keys::display::ppiVertical] = ppiV; + 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::desktopPpi] = std::round(0.5f * (ppiHScaled + ppiVScaled)); + + // refreshrate + display[keys::display::modeRefreshrate] = displayRefreshrate; + + // Master display ? + display[keys::display::isMaster] = displayMaster; + + // 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); + } + } + // Collect Renderer info as exposed by the CGL layers GLuint cglDisplayMask = -1; // Iterate over all of them. CGLRendererInfoObj rendererInfo; @@ -54,210 +138,155 @@ void MACOSInstance::enumerateGpusAndDisplays() { return; } - struct CGLRendererDesc { - int rendererID{0}; - int deviceVRAM{0}; - int majorGLVersion{0}; - int registryIDLow{0}; - int registryIDHigh{0}; - int displayMask{0}; - }; - std::vector renderers(rendererInfoCount); - // 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++) { - auto& desc = renderers[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, kCGLRPMajorGLVersion, &desc.majorGLVersion); - CGLDescribeRenderer(rendererInfo, i, kCGLRPRegistryIDLow, &desc.registryIDLow); - CGLDescribeRenderer(rendererInfo, i, kCGLRPRegistryIDHigh, &desc.registryIDHigh); CGLDescribeRenderer(rendererInfo, i, kCGLRPDisplayMask, &desc.displayMask); + CGLDescribeRenderer(rendererInfo, i, kCGLRPAccelerated, &desc.accelerated); - kCGLRPDisplayMask + // 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["A"] =desc.rendererID; - gpu["B"] =desc.deviceVRAM; - gpu["C"] =desc.majorGLVersion; + gpu[keys::gpu::vendor] = vendorName; + gpu[keys::gpu::videoMemory] = desc.deviceVRAM; + gpu["macos_rendererID"] = desc.rendererID; + gpu["macos_displayMask"] = desc.displayMask; - gpu["D"] =desc.registryIDLow; - gpu["E"] =desc.registryIDHigh; - gpu["F"] =desc.displayMask; + std::vector displayIndices; + for (int d = 0; d < (int) displayMasks.size(); d++) { + if (desc.displayMask & displayMasks[d]) { + displayIndices.push_back(d); + _displays[d][keys::display::gpu] = _gpus.size(); + } + } + gpu[keys::gpu::displays] = displayIndices; _gpus.push_back(gpu); } CGLDestroyRendererInfo(rendererInfo); - //get gpu / display information from the system profiler - FILE* stream = popen("system_profiler SPDisplaysDataType | grep -e Chipset -e VRAM -e Vendor -e \"Device ID\" -e Displays -e \"Display Type\" -e Resolution -e \"Main Display\"", "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(); + { //get gpu information from the system profiler that we don't know how to retreive otherwise + struct ChipsetModelDesc { + std::string model; + std::string vendor; + int deviceID{0}; + int videoMemory{0}; + }; + std::vector chipsetDescs; + FILE* stream = popen("system_profiler SPDisplaysDataType | grep -e Chipset -e VRAM -e Vendor -e \"Device ID\"", "r"); + std::ostringstream hostStream; + while (!feof(stream) && !ferror(stream)) { + char buf[128]; + int bytesRead = fread(buf, 1, 128, stream); + hostStream.write(buf, bytesRead); + } + std::string gpuArrayDesc = hostStream.str(); - // Find the Chipset model first - const std::regex chipsetModelToken("(Chipset Model: )(.*)"); - std::smatch found; + // Find the Chipset model first + const std::regex chipsetModelToken("(Chipset Model: )(.*)"); + std::smatch found; - while (std::regex_search(gpuArrayDesc, found, chipsetModelToken)) { - json gpu = {}; - gpu[keys::gpu::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 - gpu[keys::gpu::vendor] = findGPUVendorInDescription(gpu[keys::gpu::model].get()); - - // 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)) { - gpu[keys::gpu::videoMemory] = std::stoi(amount.str(1)) * GB_TO_MB; - } else if (std::regex_search(memAmountUnit, amount, memAmountMBToken)) { - gpu[keys::gpu::videoMemory] = std::stoi(amount.str(1)); - } else { - gpu[keys::gpu::videoMemory] = found.str(2); - } - } - - // Find the Device ID - const std::regex deviceIDToken("(Device ID: )(.*)"); - if (std::regex_search(gpuDesc, found, deviceIDToken)) { - gpu["deviceID"] = std::stoi(found.str(2)); - } - - // Enumerate the Displays - const std::regex displaysToken("(Displays: )"); - if (std::regex_search(gpuDesc, found, displaysToken)) { - std::string displayArrayDesc = found.suffix(); - std::vector displays; + while (std::regex_search(gpuArrayDesc, found, chipsetModelToken)) { + ChipsetModelDesc desc; + + desc.model = found.str(2); - int displayIndex = 0; - const std::regex displayTypeToken("(Display Type: )(.*)"); - while (std::regex_search(displayArrayDesc, found, displayTypeToken)) { - json display = {}; - display["display"] = found.str(2); - - // Find the end of the display block - displayArrayDesc = found.suffix(); - std::string displayDesc = displayArrayDesc; - const std::regex endDisplayToken("Display Type: "); - if (std::regex_search(displayArrayDesc, found, endDisplayToken)) { - displayDesc = found.prefix(); - } - - // Find the resolution - const std::regex resolutionToken("(Resolution: )(.*)"); - if (std::regex_search(displayDesc, found, deviceIDToken)) { - display["resolution"] = found.str(2); - } - - // Find is main display - const std::regex mainMonitorToken("(Main Display: )(.*)"); - if (std::regex_search(displayDesc, found, mainMonitorToken)) { - display["isMaster"] = 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 { - display["isMaster"] = "false"; + desc.videoMemory = std::stoi(memAmountUnit); } - - display["index"] = displayIndex; - displayIndex++; - - displays.push_back(display); } - if (!displays.empty()) { - gpu["displays"] = displays; + + // 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; } } - - _gpus.push_back(gpu); - } -#endif - -#ifdef Q_OS_MAC - uint32_t numDisplays = 0; - CGError error = CGGetOnlineDisplayList(0, nullptr, &numDisplays); - if (numDisplays <= 0 || error != kCGErrorSuccess) { - return; } - std::vector onlineDisplayIDs(numDisplays, 0); - error = CGGetOnlineDisplayList(onlineDisplayIDs.size(), onlineDisplayIDs.data(), &numDisplays); - if (error != kCGErrorSuccess) { - return; - } - - for (auto displayID : onlineDisplayIDs) { - auto displaySize = CGDisplayScreenSize(displayID); - - auto glmask = CGDisplayIDToOpenGLDisplayMask(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); - - 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[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; - - display["isMaster"] = displayMaster; - - display["unit"] = displayUnit; - display["vendor"] = displayVendor; - display["model"] = displayModel; - display["serial"] = displaySerial; - - display["refreshrate"] =displayRefreshrate; - display["modeWidth"] = displayModeWidth; - display["modeHeight"] = displayModeHeight; - - display["glmask"] = glmask; - - _displays.push_back(display); - } #endif } diff --git a/libraries/platform/src/platform/backend/Platform.cpp b/libraries/platform/src/platform/backend/Platform.cpp index 79687d8ba0..24ce099e0e 100644 --- a/libraries/platform/src/platform/backend/Platform.cpp +++ b/libraries/platform/src/platform/backend/Platform.cpp @@ -45,6 +45,16 @@ namespace platform { namespace keys { const char* boundsTop = "boundsTop"; const char* boundsBottom = "boundsBottom"; const char* gpu = "gpu"; + const char* ppiHorizontal = "ppiHorizontal"; + const char* ppiVertical = "ppiHorizontal"; + const char* ppi = "ppi"; + const char* physicalWidth = "physicalWidth"; + const char* physicalHeight = "physicalHeight"; + const char* modeRefreshrate = "modeRefreshrate"; + const char* modeWidth = "modeWidth"; + const char* modeHeight = "modeHeight"; + const char* desktopPpi = "desktopPpi"; + const char* isMaster = "isMaster"; } namespace memory { const char* memTotal = "memTotal"; diff --git a/libraries/platform/src/platform/backend/WINPlatform.cpp b/libraries/platform/src/platform/backend/WINPlatform.cpp index 2f0210de16..680861b550 100644 --- a/libraries/platform/src/platform/backend/WINPlatform.cpp +++ b/libraries/platform/src/platform/backend/WINPlatform.cpp @@ -127,27 +127,30 @@ void WINInstance::enumerateGpusAndDisplays() { display[keys::display::description] = ""; // Rect region of the desktop in desktop units - display["desktopRect"] = (outputDesc.AttachedToDesktop ? true : false); + //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; - // DPI - display["ppiX"] = dpiX; - display["ppiY"] = dpiY; - display["physicalWidth"] = devMode.dmPelsWidth / (float) dpiX; - display["physicalHeight"] = devMode.dmPelsHeight / (float) dpiY; - display["modeWidth"] = devMode.dmPelsWidth; - display["modeHeight"] = devMode.dmPelsHeight; - - //Average the ppiX and Y scaled vs the the true ppi - display["ppi"] = 0.5f * (dpiX + dpiY); - display["desktopPPIScale"] = 0.5f * (dpiX / (float) dpiXScaled + dpiY / (float)dpiYScaled); + // PPI & resolution + display[keys::display::ppiHorizontal] = dpiX; + display[keys::display::ppiVertical] = dpiY; + display[keys::display::physicalWidth] = devMode.dmPelsWidth / (float) dpiX; + display[keys::display::physicalHeight] = devMode.dmPelsHeight / (float) dpiY; + 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::desktopPpi] = std::round(0.5f * (dpiXScaled + dpiYScaled)); + // refreshrate - display["frequency"] = devMode.dmDisplayFrequency; - + display[keys::display::modeRefreshrate] = devMode.dmDisplayFrequency;; + + // Master display ? + display[keys::display::isMaster] = true; + // Add the display index to the list of displays of the gpu displayIndices.push_back(_displays.size()); @@ -188,11 +191,13 @@ void WINInstance::enumerateComputer() { _computer[keys::computer::vendor] = ""; _computer[keys::computer::model] = ""; +#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(); @@ -231,4 +236,4 @@ void WINInstance::enumerateNics() { free(pAdapterInfo); } #endif -} \ No newline at end of file +} From 0c26d3ef6610350068d905c9adbdd61268eff393 Mon Sep 17 00:00:00 2001 From: Samuel Gateau Date: Fri, 5 Jul 2019 13:23:19 +0200 Subject: [PATCH 19/30] clean up etc --- .../platform/src/platform/PlatformKeys.h | 4 +- .../src/platform/backend/MACOSPlatform.cpp | 4 +- .../src/platform/backend/Platform.cpp | 4 +- .../src/platform/backend/WINPlatform.cpp | 150 ++++++++++-------- 4 files changed, 87 insertions(+), 75 deletions(-) diff --git a/libraries/platform/src/platform/PlatformKeys.h b/libraries/platform/src/platform/PlatformKeys.h index fceb3071a7..9513bcc96a 100644 --- a/libraries/platform/src/platform/PlatformKeys.h +++ b/libraries/platform/src/platform/PlatformKeys.h @@ -44,15 +44,13 @@ namespace platform { namespace keys{ extern const char* boundsTop; extern const char* boundsBottom; extern const char* gpu; - extern const char* ppiHorizontal; - extern const char* ppiVertical; 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* desktopPpi; extern const char* isMaster; } namespace memory { diff --git a/libraries/platform/src/platform/backend/MACOSPlatform.cpp b/libraries/platform/src/platform/backend/MACOSPlatform.cpp index 76ad16f019..331533380b 100644 --- a/libraries/platform/src/platform/backend/MACOSPlatform.cpp +++ b/libraries/platform/src/platform/backend/MACOSPlatform.cpp @@ -100,8 +100,6 @@ void MACOSInstance::enumerateGpusAndDisplays() { display[keys::display::boundsBottom] = displayBounds.origin.y + displayBounds.size.height; // PPI & resolution - display[keys::display::ppiHorizontal] = ppiH; - display[keys::display::ppiVertical] = ppiV; display[keys::display::physicalWidth] = displaySizeWidthInches; display[keys::display::physicalHeight] = displaySizeHeightInches; display[keys::display::modeWidth] = displayModeWidth; @@ -109,7 +107,7 @@ void MACOSInstance::enumerateGpusAndDisplays() { //Average the ppiH and V for the simple ppi display[keys::display::ppi] = std::round(0.5f * (ppiH + ppiV)); - display[keys::display::desktopPpi] = std::round(0.5f * (ppiHScaled + ppiVScaled)); + display[keys::display::ppiDesktop] = std::round(0.5f * (ppiHScaled + ppiVScaled)); // refreshrate display[keys::display::modeRefreshrate] = displayRefreshrate; diff --git a/libraries/platform/src/platform/backend/Platform.cpp b/libraries/platform/src/platform/backend/Platform.cpp index 24ce099e0e..a47cb0622b 100644 --- a/libraries/platform/src/platform/backend/Platform.cpp +++ b/libraries/platform/src/platform/backend/Platform.cpp @@ -45,15 +45,13 @@ namespace platform { namespace keys { const char* boundsTop = "boundsTop"; const char* boundsBottom = "boundsBottom"; const char* gpu = "gpu"; - const char* ppiHorizontal = "ppiHorizontal"; - const char* ppiVertical = "ppiHorizontal"; 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* desktopPpi = "desktopPpi"; const char* isMaster = "isMaster"; } namespace memory { diff --git a/libraries/platform/src/platform/backend/WINPlatform.cpp b/libraries/platform/src/platform/backend/WINPlatform.cpp index 680861b550..dd332df616 100644 --- a/libraries/platform/src/platform/backend/WINPlatform.cpp +++ b/libraries/platform/src/platform/backend/WINPlatform.cpp @@ -81,90 +81,108 @@ void WINInstance::enumerateGpusAndDisplays() { // 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); - LARGE_INTEGER version; - hr = pAdapter->CheckInterfaceSupport(__uuidof(IDXGIDevice), &version); + std::wstring wDescription(adapterDesc.Description); + std::string description(wDescription.begin(), wDescription.end()); - std::wstring wDescription(adapterDesc.Description); - std::string description(wDescription.begin(), wDescription.end()); + json gpu = {}; + gpu[keys::gpu::model] = description; + gpu[keys::gpu::vendor] = findGPUVendorInDescription(gpu[keys::gpu::model].get()); + const SIZE_T BYTES_PER_MEGABYTE = 1024 * 1024; + gpu[keys::gpu::videoMemory] = (uint32_t)(adapterDesc.DedicatedVideoMemory / BYTES_PER_MEGABYTE); + gpu[keys::gpu::driver] = convertDriverVersionToString.convert(version); - json gpu = {}; - gpu[keys::gpu::model] = description; - gpu[keys::gpu::vendor] = findGPUVendorInDescription(gpu[keys::gpu::model].get()); - const SIZE_T BYTES_PER_MEGABYTE = 1024 * 1024; - gpu[keys::gpu::videoMemory] = (uint32_t)(adapterDesc.DedicatedVideoMemory / BYTES_PER_MEGABYTE); - gpu[keys::gpu::driver] = convertDriverVersionToString.convert(version); + std::vector displayIndices; - std::vector displayIndices; + UINT outputNum = 0; + IDXGIOutput* pOutput; + bool hasOutputConnectedToDesktop = false; + while (pAdapter->EnumOutputs(outputNum, &pOutput) != DXGI_ERROR_NOT_FOUND) { + // FOund an output attached to the adapter, get descriptor + DXGI_OUTPUT_DESC outputDesc; + pOutput->GetDesc(&outputDesc); + pOutput->Release(); + outputNum++; - 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); + // 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); + // 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); + // CUrrent display mode + DEVMODEW devMode; + devMode.dmSize = sizeof(DEVMODEW); + EnumDisplaySettingsW(outputDesc.DeviceName, ENUM_CURRENT_SETTINGS, &devMode); - json display = {}; + 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] = ""; + // 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; + // 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::ppiHorizontal] = dpiX; - display[keys::display::ppiVertical] = dpiY; - display[keys::display::physicalWidth] = devMode.dmPelsWidth / (float) dpiX; - display[keys::display::physicalHeight] = devMode.dmPelsHeight / (float) dpiY; - display[keys::display::modeWidth] = devMode.dmPelsWidth; - display[keys::display::modeHeight] = devMode.dmPelsHeight; + // PPI & resolution + display[keys::display::physicalWidth] = devMode.dmPelsWidth / (float) dpiX; + display[keys::display::physicalHeight] = devMode.dmPelsHeight / (float) dpiY; + 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::desktopPpi] = std::round(0.5f * (dpiXScaled + dpiYScaled)); + //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;; + // refreshrate + display[keys::display::modeRefreshrate] = devMode.dmDisplayFrequency;; - // Master display ? - display[keys::display::isMaster] = true; - - // Add the display index to the list of displays of the gpu - displayIndices.push_back(_displays.size()); + // 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] = _gpus.size(); + // And set the gpu index to the display description + display[keys::display::gpu] = (int) _gpus.size(); - // One more display desc - _displays.push_back(display); - pOutput->Release(); - outputNum++; + // WIN specific + display["win_workLeft"] = monitorInfo.rcWork.left; + display["win_workRight"] = monitorInfo.rcWork.right; + display["win_workTop"] = monitorInfo.rcWork.top; + display["win_workBottom"] = monitorInfo.rcWork.bottom; + display["win_monLeft"] = monitorInfo.rcMonitor.left; + display["win_monRight"] = monitorInfo.rcMonitor.right; + display["win_monTop"] = monitorInfo.rcMonitor.top; + display["win_monBottom"] = monitorInfo.rcMonitor.bottom; + + // One more display desc + _displays.push_back(display); + } + gpu[keys::gpu::displays] = displayIndices; + + _gpus.push_back(gpu); } - gpu[keys::gpu::displays] = displayIndices; - _gpus.push_back(gpu); pAdapter->Release(); adapterNum++; } From 9d9b80dec09c08e47731af7d502caa657d74ca79 Mon Sep 17 00:00:00 2001 From: Samuel Gateau Date: Fri, 5 Jul 2019 15:02:51 +0200 Subject: [PATCH 20/30] remove cruft on the win side and live with a crappy ppiDesktop --- .../src/platform/backend/WINPlatform.cpp | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/libraries/platform/src/platform/backend/WINPlatform.cpp b/libraries/platform/src/platform/backend/WINPlatform.cpp index dd332df616..e528618fe1 100644 --- a/libraries/platform/src/platform/backend/WINPlatform.cpp +++ b/libraries/platform/src/platform/backend/WINPlatform.cpp @@ -123,11 +123,14 @@ void WINInstance::enumerateGpusAndDisplays() { UINT dpiYScaled{ 0 }; GetDpiForMonitor(outputDesc.Monitor, MDT_EFFECTIVE_DPI, &dpiXScaled, &dpiYScaled); - // CUrrent display mode + // 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 @@ -144,8 +147,8 @@ void WINInstance::enumerateGpusAndDisplays() { display[keys::display::boundsTop] = outputDesc.DesktopCoordinates.top; // PPI & resolution - display[keys::display::physicalWidth] = devMode.dmPelsWidth / (float) dpiX; - display[keys::display::physicalHeight] = devMode.dmPelsHeight / (float) dpiY; + display[keys::display::physicalWidth] = physicalWidth; + display[keys::display::physicalHeight] = physicalHeight; display[keys::display::modeWidth] = devMode.dmPelsWidth; display[keys::display::modeHeight] = devMode.dmPelsHeight; @@ -166,14 +169,7 @@ void WINInstance::enumerateGpusAndDisplays() { display[keys::display::gpu] = (int) _gpus.size(); // WIN specific - display["win_workLeft"] = monitorInfo.rcWork.left; - display["win_workRight"] = monitorInfo.rcWork.right; - display["win_workTop"] = monitorInfo.rcWork.top; - display["win_workBottom"] = monitorInfo.rcWork.bottom; - display["win_monLeft"] = monitorInfo.rcMonitor.left; - display["win_monRight"] = monitorInfo.rcMonitor.right; - display["win_monTop"] = monitorInfo.rcMonitor.top; - display["win_monBottom"] = monitorInfo.rcMonitor.bottom; + // One more display desc _displays.push_back(display); From 6ef652038b821017df6d68cee0162daba0e63b31 Mon Sep 17 00:00:00 2001 From: Samuel Gateau Date: Fri, 5 Jul 2019 16:15:19 +0200 Subject: [PATCH 21/30] EXpose the master index for cpu, gpu and display and adjust the profuiler to support it / remove unsupported deferred for macs since now it is fixed --- .../PlatformInfoScriptingInterface.cpp | 12 +++- .../PlatformInfoScriptingInterface.h | 25 ++++++- libraries/platform/src/platform/Platform.h | 3 + .../platform/src/platform/PlatformKeys.h | 2 + libraries/platform/src/platform/Profiler.cpp | 12 ++-- .../src/platform/backend/Platform.cpp | 16 ++++- .../src/platform/backend/PlatformInstance.cpp | 69 ++++++++++++++++++- .../src/platform/backend/PlatformInstance.h | 13 ++++ libraries/shared/src/GPUIdent.cpp | 2 +- 9 files changed, 140 insertions(+), 14 deletions(-) diff --git a/interface/src/scripting/PlatformInfoScriptingInterface.cpp b/interface/src/scripting/PlatformInfoScriptingInterface.cpp index 84c4d923d0..cbd94b3dd5 100644 --- a/interface/src/scripting/PlatformInfoScriptingInterface.cpp +++ b/interface/src/scripting/PlatformInfoScriptingInterface.cpp @@ -167,7 +167,9 @@ bool PlatformInfoScriptingInterface::isStandalone() { int PlatformInfoScriptingInterface::getNumCPUs() { return platform::getNumCPUs(); } - +int PlatformInfoScriptingInterface::getMasterCPU() { + return platform::getMasterCPU(); +} QString PlatformInfoScriptingInterface::getCPU(int index) { auto desc = platform::getCPU(index); return QString(desc.dump().c_str()); @@ -176,7 +178,9 @@ QString PlatformInfoScriptingInterface::getCPU(int index) { int PlatformInfoScriptingInterface::getNumGPUs() { return platform::getNumGPUs(); } - +int PlatformInfoScriptingInterface::getMasterGPU() { + return platform::getMasterGPU(); +} QString PlatformInfoScriptingInterface::getGPU(int index) { auto desc = platform::getGPU(index); return QString(desc.dump().c_str()); @@ -185,7 +189,9 @@ QString PlatformInfoScriptingInterface::getGPU(int index) { int PlatformInfoScriptingInterface::getNumDisplays() { return platform::getNumDisplays(); } - +int PlatformInfoScriptingInterface::getMasterDisplay() { + return platform::getMasterDisplay(); +} QString PlatformInfoScriptingInterface::getDisplay(int index) { auto desc = platform::getDisplay(index); return QString(desc.dump().c_str()); diff --git a/interface/src/scripting/PlatformInfoScriptingInterface.h b/interface/src/scripting/PlatformInfoScriptingInterface.h index 113509d6d9..9ac67ec0bd 100644 --- a/interface/src/scripting/PlatformInfoScriptingInterface.h +++ b/interface/src/scripting/PlatformInfoScriptingInterface.h @@ -94,8 +94,8 @@ public slots: * @returns {string} The graphics card type. * @deprecated This function is deprecated and will be removed. * use getNumGPUs() to know the number of GPUs in the hardware, at least one is expected - * use getGPU(0)["vendor"] to get the brand of the vendor - * use getGPU(0)["model"] to get the model name of the gpu + * use getGPU(getMasterGPU())["vendor"] to get the brand of the vendor + * use getGPU(getMasterGPU())["model"] to get the model name of the gpu */ QString getGraphicsCardType(); @@ -135,6 +135,13 @@ public slots: */ int getNumCPUs(); + /**jsdoc + * Get the index of the master CPU. + * @function PlatformInfo.getMasterCPU + * @returns {number} The index of the master CPU detected on the hardware platform. + */ + int getMasterCPU(); + /**jsdoc * Get the description of the CPU at the index parameter * expected fields are: @@ -152,6 +159,13 @@ public slots: */ int getNumGPUs(); + /**jsdoc + * Get the index of the master GPU. + * @function PlatformInfo.getMasterGPU + * @returns {number} The index of the master GPU detected on the hardware platform. + */ + int getMasterGPU(); + /**jsdoc * Get the description of the GPU at the index parameter * expected fields are: @@ -169,6 +183,13 @@ public slots: */ int getNumDisplays(); + /**jsdoc + * Get the index of the master Display. + * @function PlatformInfo.getMasterDisplay + * @returns {number} The index of the master Display detected on the hardware platform. + */ + int getMasterDisplay(); + /**jsdoc * Get the description of the Display at the index parameter * expected fields are: diff --git a/libraries/platform/src/platform/Platform.h b/libraries/platform/src/platform/Platform.h index 9405c77ae0..8cda6332ee 100644 --- a/libraries/platform/src/platform/Platform.h +++ b/libraries/platform/src/platform/Platform.h @@ -21,12 +21,15 @@ bool enumeratePlatform(); int getNumCPUs(); json getCPU(int index); +int getMasterCPU(); int getNumGPUs(); json getGPU(int index); +int getMasterGPU(); int getNumDisplays(); json getDisplay(int index); +int getMasterDisplay(); json getMemory(); diff --git a/libraries/platform/src/platform/PlatformKeys.h b/libraries/platform/src/platform/PlatformKeys.h index 9513bcc96a..5008a4f6ce 100644 --- a/libraries/platform/src/platform/PlatformKeys.h +++ b/libraries/platform/src/platform/PlatformKeys.h @@ -20,6 +20,7 @@ namespace platform { namespace keys{ extern const char* model; extern const char* clockSpeed; extern const char* numCores; + extern const char* isMaster; } namespace gpu { extern const char* vendor; @@ -31,6 +32,7 @@ namespace platform { namespace keys{ extern const char* videoMemory; extern const char* driver; extern const char* displays; + extern const char* isMaster; } namespace nic { extern const char* mac; diff --git a/libraries/platform/src/platform/Profiler.cpp b/libraries/platform/src/platform/Profiler.cpp index 1c055a5ec9..3e4dff9fd1 100644 --- a/libraries/platform/src/platform/Profiler.cpp +++ b/libraries/platform/src/platform/Profiler.cpp @@ -32,9 +32,9 @@ Profiler::Tier Profiler::profilePlatform() { return platformTier; } - // Not filtered yet, let s try to make sense of the cpu and gpu info - auto cpuInfo = platform::getCPU(0); - auto gpuInfo = platform::getGPU(0); + // Not filtered yet, let s try to make sense of the master cpu and master gpu info + auto cpuInfo = platform::getCPU(platform::getMasterCPU()); + auto gpuInfo = platform::getGPU(platform::getMasterGPU()); if (filterOnProcessors(computerInfo, cpuInfo, gpuInfo, platformTier)) { return platformTier; } @@ -133,10 +133,12 @@ bool filterOnProcessors(const platform::json& computer, const platform::json& cp // YES on macos EXCEPT for macbookair with gpu intel iris or intel HD 6000 bool Profiler::isRenderMethodDeferredCapable() { #if defined(Q_OS_MAC) + // Deferred works correctly on every supported macos platform at the moment, let s enable it +/* auto computer = platform::getComputer(); const auto computerModel = (computer.count(keys::computer::model) ? computer[keys::computer::model].get() : ""); - auto gpuInfo = platform::getGPU(0); + auto gpuInfo = platform::getGPU(getMasterGPU()); const auto gpuModel = (gpuInfo.count(keys::gpu::model) ? gpuInfo[keys::gpu::model].get() : ""); @@ -154,7 +156,7 @@ bool Profiler::isRenderMethodDeferredCapable() { if ((gpuModel.find("Intel ") != std::string::npos)) { return false; } - +*/ return true; #elif defined(Q_OS_ANDROID) return false; diff --git a/libraries/platform/src/platform/backend/Platform.cpp b/libraries/platform/src/platform/backend/Platform.cpp index a47cb0622b..17d9d8019e 100644 --- a/libraries/platform/src/platform/backend/Platform.cpp +++ b/libraries/platform/src/platform/backend/Platform.cpp @@ -21,7 +21,8 @@ namespace platform { namespace keys { const char* model = "model"; const char* clockSpeed = "clockSpeed"; const char* numCores = "numCores"; - } + const char* isMaster = "isMaster"; + } namespace gpu { const char* vendor = "vendor"; const char* vendor_NVIDIA = "NVIDIA"; @@ -32,6 +33,7 @@ namespace platform { namespace keys { const char* videoMemory = "videoMemory"; const char* driver = "driver"; const char* displays = "displays"; + const char* isMaster = "isMaster"; } namespace nic { const char* mac = "mac"; @@ -127,6 +129,10 @@ json platform::getCPU(int index) { return _instance->getCPU(index); } +int platform::getMasterCPU() { + return _instance->getMasterCPU(); +} + int platform::getNumGPUs() { return _instance->getNumGPUs(); } @@ -135,6 +141,10 @@ json platform::getGPU(int index) { return _instance->getGPU(index); } +int platform::getMasterGPU() { + return _instance->getMasterGPU(); +} + int platform::getNumDisplays() { return _instance->getNumDisplays(); } @@ -143,6 +153,10 @@ json platform::getDisplay(int index) { return _instance->getDisplay(index); } +int platform::getMasterDisplay() { + return _instance->getMasterDisplay(); +} + json platform::getMemory() { return _instance->getMemory(); } diff --git a/libraries/platform/src/platform/backend/PlatformInstance.cpp b/libraries/platform/src/platform/backend/PlatformInstance.cpp index 4fd4a9aa2a..bfc2783516 100644 --- a/libraries/platform/src/platform/backend/PlatformInstance.cpp +++ b/libraries/platform/src/platform/backend/PlatformInstance.cpp @@ -16,17 +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(); 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 < _displays.size(); ++i) { + const auto& display = _displays[i]; + if (display.count(keys::display::isMaster)) { + if (display[keys::display::isMaster].get()) { + _masterDisplay = i; + break; + } + } + } + // NO master display found, return the first one or NOT_FOUND if no display + if (_masterDisplay == NOT_FOUND) { + if (!_displays.empty()) { + _masterDisplay = 0; + _displays[0][keys::display::isMaster] = true; + } + } + } + + // From the master display decide the master gpu + { + _masterGPU = NOT_FOUND; + if (_masterDisplay != NOT_FOUND) { + const auto& display = _displays[_masterDisplay]; + // FInd the GPU index of the master display + if (display.count(keys::display::gpu)) { + _masterGPU = display[keys::display::gpu]; + _gpus[_masterGPU][keys::gpu::isMaster] = true; + } + } + // NO master GPU found from master display, bummer, return the first one or NOT_FOUND if no display + if (_masterGPU == NOT_FOUND) { + if (!_gpus.empty()) { + _masterGPU = 0; + _gpus[0][keys::gpu::isMaster] = true; + } + } + } +} + void Instance::enumerateNics() { QNetworkInterface interface; foreach(interface, interface.allInterfaces()) { @@ -56,6 +122,7 @@ json Instance::getGPU(int index) { return _gpus.at(index); } + json Instance::getDisplay(int index) { assert(index <(int) _displays.size()); @@ -99,8 +166,6 @@ json Instance::listAllKeys() { keys::gpu::driver, keys::gpu::displays, - keys::display::description, - keys::display::name, keys::display::boundsLeft, keys::display::boundsRight, keys::display::boundsTop, diff --git a/libraries/platform/src/platform/backend/PlatformInstance.h b/libraries/platform/src/platform/backend/PlatformInstance.h index e66aa94846..069124853e 100644 --- a/libraries/platform/src/platform/backend/PlatformInstance.h +++ b/libraries/platform/src/platform/backend/PlatformInstance.h @@ -17,16 +17,21 @@ namespace platform { class Instance { public: + const int NOT_FOUND { -1 }; + bool virtual enumeratePlatform(); int getNumCPUs() { return (int)_cpus.size(); } json getCPU(int index); + int getMasterCPU() const { return _masterCPU; } int getNumGPUs() { return (int)_gpus.size(); } json getGPU(int index); + int getMasterGPU() const { return _masterGPU; } int getNumDisplays() { return (int)_displays.size(); } json getDisplay(int index); + int getMasterDisplay() const { return _masterDisplay; } json getMemory() { return _memory; } @@ -54,6 +59,14 @@ protected: std::vector _nics; json _memory; json _computer; + + int _masterCPU{ -1 }; + int _masterGPU{ -1 }; + int _masterDisplay{ -1 }; + + // Traverse the cpus, gpus and displays to update the "master" index in each domain + void updateMasterIndices(); + }; } // namespace platform diff --git a/libraries/shared/src/GPUIdent.cpp b/libraries/shared/src/GPUIdent.cpp index c195b2ec3a..6f2b5600ee 100644 --- a/libraries/shared/src/GPUIdent.cpp +++ b/libraries/shared/src/GPUIdent.cpp @@ -289,7 +289,7 @@ GPUIdent* GPUIdent::ensureQuery(const QString& vendor, const QString& renderer) nlohmann::json output = {}; output["model"] = deviceName; - output["coordinatesleft"] = test->DesktopCoordinates.left; + output["coordsinatesleft"] = test->DesktopCoordinates.left; output["coordinatesright"] = test->DesktopCoordinates.right; output["coordinatestop"] = test->DesktopCoordinates.top; output["coordinatesbottom"] = test->DesktopCoordinates.bottom; From 11f036246e98d4ac320e0fbd6db3c3f343c459fc Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 5 Jul 2019 17:52:44 +0200 Subject: [PATCH 22/30] Implement the ppi scaling in sync with the platform tier --- interface/src/PerformanceManager.cpp | 20 ++++++++++++++++++- .../src/platform/backend/MACOSPlatform.cpp | 2 +- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/interface/src/PerformanceManager.cpp b/interface/src/PerformanceManager.cpp index 0a028f95cc..58fb5674ff 100644 --- a/interface/src/PerformanceManager.cpp +++ b/interface/src/PerformanceManager.cpp @@ -10,6 +10,8 @@ // #include "PerformanceManager.h" +#include +#include #include #include "scripting/RenderScriptingInterface.h" @@ -65,6 +67,16 @@ 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 ppi{96}; + 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)) { + ppi = masterDisplay[platform::keys::display::ppi]; + recommandedPpiScale = std::min(1.0f, RECOMMANDED_PPI[preset] / (float) ppi); + } switch (preset) { case PerformancePreset::HIGH: @@ -72,17 +84,21 @@ void PerformanceManager::applyPerformancePreset(PerformanceManager::PerformanceP RenderScriptingInterface::RenderMethod::DEFERRED : RenderScriptingInterface::RenderMethod::FORWARD ) ); + RenderScriptingInterface::getInstance()->setViewportResolutionScale(recommandedPpiScale); + RenderScriptingInterface::getInstance()->setShadowsEnabled(true); qApp->getRefreshRateManager().setRefreshRateProfile(RefreshRateManager::RefreshRateProfile::REALTIME); DependencyManager::get()->setWorldDetailQuality(0.5f); - + break; case PerformancePreset::MID: RenderScriptingInterface::getInstance()->setRenderMethod((isDeferredCapable ? RenderScriptingInterface::RenderMethod::DEFERRED : RenderScriptingInterface::RenderMethod::FORWARD)); + RenderScriptingInterface::getInstance()->setViewportResolutionScale(recommandedPpiScale); + RenderScriptingInterface::getInstance()->setShadowsEnabled(false); qApp->getRefreshRateManager().setRefreshRateProfile(RefreshRateManager::RefreshRateProfile::INTERACTIVE); DependencyManager::get()->setWorldDetailQuality(0.5f); @@ -93,6 +109,8 @@ void PerformanceManager::applyPerformancePreset(PerformanceManager::PerformanceP RenderScriptingInterface::getInstance()->setShadowsEnabled(false); qApp->getRefreshRateManager().setRefreshRateProfile(RefreshRateManager::RefreshRateProfile::ECO); + RenderScriptingInterface::getInstance()->setViewportResolutionScale(recommandedPpiScale); + DependencyManager::get()->setWorldDetailQuality(0.75f); break; diff --git a/libraries/platform/src/platform/backend/MACOSPlatform.cpp b/libraries/platform/src/platform/backend/MACOSPlatform.cpp index 331533380b..66c9cd2c5d 100644 --- a/libraries/platform/src/platform/backend/MACOSPlatform.cpp +++ b/libraries/platform/src/platform/backend/MACOSPlatform.cpp @@ -113,7 +113,7 @@ void MACOSInstance::enumerateGpusAndDisplays() { display[keys::display::modeRefreshrate] = displayRefreshrate; // Master display ? - display[keys::display::isMaster] = displayMaster; + display[keys::display::isMaster] = (displayMaster ? true : false); // Macos specific display["macos_unit"] = displayUnit; From 07983cd642a917a2ec6a9766e18800135a3c7fa4 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Fri, 5 Jul 2019 09:02:34 -0700 Subject: [PATCH 23/30] Don't shut down launcher until interface window is shown --- launchers/win32/LauncherApp.cpp | 2 +- launchers/win32/LauncherDlg.cpp | 6 ++---- launchers/win32/LauncherManager.cpp | 10 +++++----- launchers/win32/LauncherUtils.cpp | 29 ++++++++++++++++++++++++++--- launchers/win32/LauncherUtils.h | 11 +++++++++-- 5 files changed, 43 insertions(+), 15 deletions(-) diff --git a/launchers/win32/LauncherApp.cpp b/launchers/win32/LauncherApp.cpp index a432a0b116..c15ba75a9b 100644 --- a/launchers/win32/LauncherApp.cpp +++ b/launchers/win32/LauncherApp.cpp @@ -34,7 +34,7 @@ CLauncherApp theApp; BOOL CLauncherApp::InitInstance() { // Close interface if is running int interfacePID = -1; - if (LauncherUtils::IsProcessRunning(L"interface.exe", interfacePID)) { + if (LauncherUtils::isProcessRunning(L"interface.exe", interfacePID)) { LauncherUtils::shutdownProcess(interfacePID, 0); } int iNumOfArgs; diff --git a/launchers/win32/LauncherDlg.cpp b/launchers/win32/LauncherDlg.cpp index 83af659208..c308efe3cc 100644 --- a/launchers/win32/LauncherDlg.cpp +++ b/launchers/win32/LauncherDlg.cpp @@ -629,8 +629,7 @@ void CLauncherDlg::OnTimer(UINT_PTR nIDEvent) { ::SetForegroundWindow(_applicationWND); ::SetActiveWindow(_applicationWND); } - int interfacePID = -1; - if (LauncherUtils::IsProcessRunning(L"interface.exe", interfacePID)) { + if (LauncherUtils::isProcessWindowOpened(L"interface.exe")) { exit(0); } } @@ -654,8 +653,7 @@ void CLauncherDlg::OnTimer(UINT_PTR nIDEvent) { } _splashStep++; } else if (theApp._manager.shouldShutDown()) { - int interfacePID = -1; - if (LauncherUtils::IsProcessRunning(L"interface.exe", interfacePID)) { + if (LauncherUtils::isProcessWindowOpened(L"interface.exe")) { exit(0); } } diff --git a/launchers/win32/LauncherManager.cpp b/launchers/win32/LauncherManager.cpp index 619ebe9c42..ab3158d220 100644 --- a/launchers/win32/LauncherManager.cpp +++ b/launchers/win32/LauncherManager.cpp @@ -111,7 +111,7 @@ BOOL LauncherManager::installLauncher() { // Kill of running before self-copy addToLog(_T("Installing Launcher.")); int launcherPID = -1; - if (LauncherUtils::IsProcessRunning(LAUNCHER_EXE_FILENAME, launcherPID)) { + if (LauncherUtils::isProcessRunning(LAUNCHER_EXE_FILENAME, launcherPID)) { if (!LauncherUtils::shutdownProcess(launcherPID, 0)) { addToLog(_T("Error shutting down the Launcher")); } @@ -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; diff --git a/launchers/win32/LauncherUtils.cpp b/launchers/win32/LauncherUtils.cpp index 39964cc457..e72720eb55 100644 --- a/launchers/win32/LauncherUtils.cpp +++ b/launchers/win32/LauncherUtils.cpp @@ -49,13 +49,36 @@ BOOL LauncherUtils::shutdownProcess(DWORD dwProcessId, UINT uExitCode) { return result; } -BOOL LauncherUtils::IsProcessRunning(const wchar_t *processName, int& processID) { +BOOL CALLBACK LauncherUtils::isWindowOpenedCallback(HWND hWnd, LPARAM lparam) { + ProcessData* processData = reinterpret_cast(lparam); + if (processData) { + DWORD idptr; + GetWindowThreadProcessId(hWnd, &idptr); + if (idptr && (int)(idptr) == processData->processID) { + processData->isOpened = IsWindowVisible(hWnd); + return FALSE; + } + } + return TRUE; +} + +BOOL LauncherUtils::isProcessWindowOpened(const wchar_t *processName) { + ProcessData processData; + BOOL result = isProcessRunning(processName, processData.processID); + if (result) { + EnumWindows(LauncherUtils::isWindowOpenedCallback, reinterpret_cast(&processData)); + return processData.isOpened; + } + return result; +} + +BOOL LauncherUtils::isProcessRunning(const wchar_t *processName, int& processID) { bool exists = false; PROCESSENTRY32 entry; entry.dwSize = sizeof(PROCESSENTRY32); HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); - + if (Process32First(snapshot, &entry)) { while (Process32Next(snapshot, &entry)) { if (!_wcsicmp(entry.szExeFile, processName)) { @@ -69,7 +92,7 @@ BOOL LauncherUtils::IsProcessRunning(const wchar_t *processName, int& processID) 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 diff --git a/launchers/win32/LauncherUtils.h b/launchers/win32/LauncherUtils.h index f5ce04b386..bf1516155a 100644 --- a/launchers/win32/LauncherUtils.h +++ b/launchers/win32/LauncherUtils.h @@ -66,6 +66,11 @@ public: void setCallback(std::function 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,12 +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, int& processID); + static BOOL CALLBACK isWindowOpenedCallback(HWND hWnd, LPARAM lparam); + static BOOL isProcessRunning(const wchar_t *processName, int& processID); + static BOOL isProcessWindowOpened(const wchar_t *processName); static BOOL shutdownProcess(DWORD dwProcessId, UINT uExitCode); static BOOL insertRegistryKey(const std::string& regPath, const std::string& name, const std::string& value); static BOOL insertRegistryKey(const std::string& regPath, const std::string& name, DWORD value); static BOOL deleteFileOrDirectory(const CString& dirPath, bool noRecycleBin = true); - static HRESULT CreateLink(LPCWSTR lpszPathObj, LPCSTR lpszPathLink, LPCWSTR lpszDesc, LPCWSTR lpszArgs = _T("")); + static HRESULT createLink(LPCWSTR lpszPathObj, LPCSTR lpszPathLink, LPCWSTR lpszDesc, LPCWSTR lpszArgs = _T("")); static BOOL hMac256(const CString& message, const char* key, CString& hashOut); static uint64_t extractZip(const std::string& zipFile, const std::string& path, std::vector& files); static BOOL deleteRegistryKey(const CString& registryPath); From 1aa067db749cb8c2ece7e3c0ccbcdbd58445b412 Mon Sep 17 00:00:00 2001 From: Samuel Gateau Date: Fri, 5 Jul 2019 18:54:33 +0200 Subject: [PATCH 24/30] address warning --- libraries/platform/src/platform/backend/PlatformInstance.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/platform/src/platform/backend/PlatformInstance.cpp b/libraries/platform/src/platform/backend/PlatformInstance.cpp index bfc2783516..038521d398 100644 --- a/libraries/platform/src/platform/backend/PlatformInstance.cpp +++ b/libraries/platform/src/platform/backend/PlatformInstance.cpp @@ -54,7 +54,7 @@ void Instance::updateMasterIndices() { // Go through the displays list { _masterDisplay = NOT_FOUND; - for (int i = 0; i < _displays.size(); ++i) { + 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()) { From a94eb4d44b2e34e7aacd271f0eced98bd23f3795 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Fri, 5 Jul 2019 11:09:36 -0700 Subject: [PATCH 25/30] Allow the launcher window to be moved --- launchers/win32/LauncherDlg.cpp | 42 +++++++++++++++++++++++++++++---- launchers/win32/LauncherDlg.h | 16 +++++++++---- 2 files changed, 49 insertions(+), 9 deletions(-) diff --git a/launchers/win32/LauncherDlg.cpp b/launchers/win32/LauncherDlg.cpp index c308efe3cc..a8fdf8912b 100644 --- a/launchers/win32/LauncherDlg.cpp +++ b/launchers/win32/LauncherDlg.cpp @@ -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); } diff --git a/launchers/win32/LauncherDlg.h b/launchers/win32/LauncherDlg.h index 9d34fe5503..4d830c2e21 100644 --- a/launchers/win32/LauncherDlg.h +++ b/launchers/win32/LauncherDlg.h @@ -60,12 +60,18 @@ protected: DrawStep _drawStep { DrawStep::DrawLogo }; BOOL getTextFormat(int ResID, TextFormat& formatOut); void showWindows(std::vector windows, bool show); + POINT getMouseCoords(MSG* pMsg); - bool _isConsoleRunning{ false }; - bool _isInstalling{ false }; - bool _isFirstDraw{ false }; - bool _showSplash{ true }; - int _splashStep{ 0 }; + + bool _isConsoleRunning { false }; + bool _isInstalling { false }; + bool _isFirstDraw { false }; + bool _showSplash { true }; + + bool _draggingWindow { false }; + POINT _dragOffset; + + int _splashStep { 0 }; float _logoRotation { 0.0f }; HICON m_hIcon; From eb79752455bc71842cd64eab06769eadbfb0bf45 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 5 Jul 2019 12:00:17 -0700 Subject: [PATCH 26/30] BUGZ-930: No more auto-LOD adjustment for SimplifiedUI users --- scripts/simplifiedUI/ui/simplifiedUI.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/scripts/simplifiedUI/ui/simplifiedUI.js b/scripts/simplifiedUI/ui/simplifiedUI.js index 81f917e1c9..2402895f11 100644 --- a/scripts/simplifiedUI/ui/simplifiedUI.js +++ b/scripts/simplifiedUI/ui/simplifiedUI.js @@ -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."); From 4223800af726b2a0784adfbbc761c7343cb4951f Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 5 Jul 2019 12:17:28 -0700 Subject: [PATCH 27/30] BUGZ-923: Fix an edge case in Audio I/O devices in Settings -> About --- .../qml/hifi/simplifiedUI/settingsApp/about/About.qml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/simplifiedUI/settingsApp/about/About.qml b/interface/resources/qml/hifi/simplifiedUI/settingsApp/about/About.qml index 7fa9b63dab..d562aae70d 100644 --- a/interface/resources/qml/hifi/simplifiedUI/settingsApp/about/About.qml +++ b/interface/resources/qml/hifi/simplifiedUI/settingsApp/about/About.qml @@ -25,6 +25,14 @@ Flickable { if (visible) { root.contentX = 0; root.contentY = 0; + + // When the user clicks the About tab, refresh the audio I/O model so that + // the delegate Component.onCompleted handlers fire, which will update + // the text that appears in the About screen. + audioOutputDevices.model = undefined; + audioOutputDevices.model = AudioScriptingInterface.devices.output; + audioInputDevices.model = undefined; + audioInputDevices.model = AudioScriptingInterface.devices.input; } } @@ -207,7 +215,6 @@ Flickable { Layout.preferredWidth: parent.width Layout.preferredHeight: contentItem.height interactive: false - model: AudioScriptingInterface.devices.input delegate: Item { Component.onCompleted: { if (HMD.active && selectedHMD) { @@ -241,7 +248,6 @@ Flickable { Layout.preferredWidth: parent.width Layout.preferredHeight: contentItem.height interactive: false - model: AudioScriptingInterface.devices.output delegate: Item { Component.onCompleted: { if (HMD.active && selectedHMD) { From 38ad93a7edb9db9ce593e191a12d8b5e5dda6e4e Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 5 Jul 2019 12:24:05 -0700 Subject: [PATCH 28/30] BUGZ-917: Fix log spam in NameCard.qml due to errant line of code --- interface/resources/qml/hifi/NameCard.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/NameCard.qml b/interface/resources/qml/hifi/NameCard.qml index 7e8218b7df..2cf07e32bf 100644 --- a/interface/resources/qml/hifi/NameCard.qml +++ b/interface/resources/qml/hifi/NameCard.qml @@ -400,7 +400,8 @@ Item { size: 24; x: 120 anchors.verticalCenter: nameCardConnectionInfoImage.verticalCenter - anchors.left: has3DHTML ? nameCardConnectionInfoText.right + 10 : avatarImage.right + anchors.left: has3DHTML ? nameCardConnectionInfoText.right : avatarImage.right + anchors.leftMargin: has3DHTML ? 10 : 0 } MouseArea { anchors.fill:nameCardRemoveConnectionImage From b4e86741e0543261ff55e6c1001ed9d7c6ca6613 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Sat, 6 Jul 2019 01:13:38 +0200 Subject: [PATCH 29/30] Adress typo in gpuident and add extra checks on the recommended scale value --- interface/src/PerformanceManager.cpp | 9 ++++++--- libraries/shared/src/GPUIdent.cpp | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/interface/src/PerformanceManager.cpp b/interface/src/PerformanceManager.cpp index 58fb5674ff..ec12ab0404 100644 --- a/interface/src/PerformanceManager.cpp +++ b/interface/src/PerformanceManager.cpp @@ -70,12 +70,15 @@ void PerformanceManager::applyPerformancePreset(PerformanceManager::PerformanceP auto masterDisplay = platform::getDisplay(platform::getMasterDisplay()); // eval recommanded PPI and Scale - float ppi{96}; 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)) { - ppi = masterDisplay[platform::keys::display::ppi]; - recommandedPpiScale = std::min(1.0f, RECOMMANDED_PPI[preset] / (float) 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) { diff --git a/libraries/shared/src/GPUIdent.cpp b/libraries/shared/src/GPUIdent.cpp index 6f2b5600ee..c195b2ec3a 100644 --- a/libraries/shared/src/GPUIdent.cpp +++ b/libraries/shared/src/GPUIdent.cpp @@ -289,7 +289,7 @@ GPUIdent* GPUIdent::ensureQuery(const QString& vendor, const QString& renderer) nlohmann::json output = {}; output["model"] = deviceName; - output["coordsinatesleft"] = test->DesktopCoordinates.left; + output["coordinatesleft"] = test->DesktopCoordinates.left; output["coordinatesright"] = test->DesktopCoordinates.right; output["coordinatestop"] = test->DesktopCoordinates.top; output["coordinatesbottom"] = test->DesktopCoordinates.bottom; From 352f9590b16eee2ea1e4242f097c89ff0773886d Mon Sep 17 00:00:00 2001 From: RebeccaStankus Date: Fri, 5 Jul 2019 16:17:47 -0700 Subject: [PATCH 30/30] Fixed Qt.resolvedUrl format --- scripts/system/create/entityList/qml/EntityList.qml | 2 +- scripts/system/create/qml/EditTabView.qml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/system/create/entityList/qml/EntityList.qml b/scripts/system/create/entityList/qml/EntityList.qml index a70fc6d15d..8f92ffe6ce 100644 --- a/scripts/system/create/entityList/qml/EntityList.qml +++ b/scripts/system/create/entityList/qml/EntityList.qml @@ -1,6 +1,6 @@ WebView { id: entityListToolWebView - url: QT.resolvedURL("../html/entityList.html") + url: Qt.resolvedUrl("../html/entityList.html") enabled: true blurOnCtrlShift: false } diff --git a/scripts/system/create/qml/EditTabView.qml b/scripts/system/create/qml/EditTabView.qml index f90a962f7a..a0cff70d50 100644 --- a/scripts/system/create/qml/EditTabView.qml +++ b/scripts/system/create/qml/EditTabView.qml @@ -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 }