From 68480f67607728ae080557fc8ce7b75b378e1c39 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Sat, 9 Feb 2019 10:49:18 -0800 Subject: [PATCH 01/44] Replace glm::packSnorm3x10_1x2() with fast SIMD implementation --- .../src/graphics/BufferViewHelpers.cpp | 4 +-- .../src/model-baker/BuildGraphicsMeshTask.cpp | 4 +-- libraries/render-utils/src/Model.cpp | 6 ++-- libraries/shared/src/GLMHelpers.h | 36 +++++++++++++++++++ 4 files changed, 43 insertions(+), 7 deletions(-) diff --git a/libraries/graphics/src/graphics/BufferViewHelpers.cpp b/libraries/graphics/src/graphics/BufferViewHelpers.cpp index 4c57abdfd4..301f5d8d73 100644 --- a/libraries/graphics/src/graphics/BufferViewHelpers.cpp +++ b/libraries/graphics/src/graphics/BufferViewHelpers.cpp @@ -257,7 +257,7 @@ template struct GpuVec3ToGlm : GpuToGlmAdapter { static T get(con case gpu::FLOAT: view.edit(index) = value; return true; case gpu::NUINT8: CHECK_SIZE(glm::uint32); view.edit(index) = glm::packUnorm4x8(glm::fvec4(value,0.0f)); return true; case gpu::UINT8: view.edit(index) = value; return true; - case gpu::NINT2_10_10_10: view.edit(index) = glm::packSnorm3x10_1x2(glm::fvec4(value,0.0f)); return true; + case gpu::NINT2_10_10_10: view.edit(index) = glm_packSnorm3x10_1x2(glm::fvec4(value,0.0f)); return true; default: break; } error("GpuVec3ToGlm::set", view, index, hint); return false; } @@ -295,7 +295,7 @@ template struct GpuVec4ToGlm : GpuToGlmAdapter { static T get(const case gpu::FLOAT: view.edit(index) = value; return true; case gpu::HALF: CHECK_SIZE(glm::uint64); view.edit(index) = glm::packHalf4x16(value); return true; case gpu::UINT8: view.edit(index) = value; return true; - case gpu::NINT2_10_10_10: view.edit(index) = glm::packSnorm3x10_1x2(value); return true; + case gpu::NINT2_10_10_10: view.edit(index) = glm_packSnorm3x10_1x2(value); return true; case gpu::NUINT16: CHECK_SIZE(glm::uint64); view.edit(index) = glm::packUnorm4x16(value); return true; case gpu::NUINT8: CHECK_SIZE(glm::uint32); view.edit(index) = glm::packUnorm4x8(value); return true; default: break; diff --git a/libraries/model-baker/src/model-baker/BuildGraphicsMeshTask.cpp b/libraries/model-baker/src/model-baker/BuildGraphicsMeshTask.cpp index 370add2c2e..c41431f940 100644 --- a/libraries/model-baker/src/model-baker/BuildGraphicsMeshTask.cpp +++ b/libraries/model-baker/src/model-baker/BuildGraphicsMeshTask.cpp @@ -125,8 +125,8 @@ void buildGraphicsMesh(const hfm::Mesh& hfmMesh, graphics::MeshPointer& graphics #if HFM_PACK_NORMALS const auto normal = normalizeDirForPacking(*normalIt); const auto tangent = normalizeDirForPacking(*tangentIt); - const auto packedNormal = glm::packSnorm3x10_1x2(glm::vec4(normal, 0.0f)); - const auto packedTangent = glm::packSnorm3x10_1x2(glm::vec4(tangent, 0.0f)); + const auto packedNormal = glm_packSnorm3x10_1x2(glm::vec4(normal, 0.0f)); + const auto packedTangent = glm_packSnorm3x10_1x2(glm::vec4(tangent, 0.0f)); #else const auto packedNormal = *normalIt; const auto packedTangent = *tangentIt; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index da8dceb176..9489166f43 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1594,9 +1594,9 @@ void packBlendshapeOffsetTo_Pos_F32_3xSN10_Nor_3xSN10_Tan_3xSN10(glm::uvec4& pac packed = glm::uvec4( glm::floatBitsToUint(len), - glm::packSnorm3x10_1x2(glm::vec4(normalizedPos, 0.0f)), - glm::packSnorm3x10_1x2(glm::vec4(unpacked.normalOffset, 0.0f)), - glm::packSnorm3x10_1x2(glm::vec4(unpacked.tangentOffset, 0.0f)) + glm_packSnorm3x10_1x2(glm::vec4(normalizedPos, 0.0f)), + glm_packSnorm3x10_1x2(glm::vec4(unpacked.normalOffset, 0.0f)), + glm_packSnorm3x10_1x2(glm::vec4(unpacked.tangentOffset, 0.0f)) ); } diff --git a/libraries/shared/src/GLMHelpers.h b/libraries/shared/src/GLMHelpers.h index e7aaace1ae..e50162d8a4 100644 --- a/libraries/shared/src/GLMHelpers.h +++ b/libraries/shared/src/GLMHelpers.h @@ -315,6 +315,42 @@ inline void glm_mat4u_mul(const glm::mat4& m1, const glm::mat4& m2, glm::mat4& r #endif } +// +// Fast replacement of glm::packSnorm3x10_1x2() +// The SSE2 version quantizes using round to nearest even. +// The glm version quantizes using round away from zero. +// +inline uint32_t glm_packSnorm3x10_1x2(vec4 const& v) { + + union i10i10i10i2 { + struct { + int x : 10; + int y : 10; + int z : 10; + int w : 2; + } data; + uint32_t pack; + } Result; + +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + __m128 vclamp = _mm_min_ps(_mm_max_ps(_mm_loadu_ps((float*)&v[0]), _mm_set1_ps(-1.0f)), _mm_set1_ps(1.0f)); + __m128i vpack = _mm_cvtps_epi32(_mm_mul_ps(vclamp, _mm_setr_ps(511.f, 511.f, 511.f, 1.f))); + + Result.data.x = _mm_cvtsi128_si32(vpack); + Result.data.y = _mm_cvtsi128_si32(_mm_shuffle_epi32(vpack, _MM_SHUFFLE(1,1,1,1))); + Result.data.z = _mm_cvtsi128_si32(_mm_shuffle_epi32(vpack, _MM_SHUFFLE(2,2,2,2))); + Result.data.w = _mm_cvtsi128_si32(_mm_shuffle_epi32(vpack, _MM_SHUFFLE(3,3,3,3))); +#else + ivec4 const Pack(round(clamp(v, -1.0f, 1.0f) * vec4(511.f, 511.f, 511.f, 1.f))); + + Result.data.x = Pack.x; + Result.data.y = Pack.y; + Result.data.z = Pack.z; + Result.data.w = Pack.w; +#endif + return Result.pack; +} + // convert float to int, using round-to-nearest-even (undefined on overflow) inline int fastLrintf(float x) { #if GLM_ARCH & GLM_ARCH_SSE2_BIT From 6f5514b5e3cfe920c3b634c4370c52071eaf30ab Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Sat, 9 Feb 2019 10:57:06 -0800 Subject: [PATCH 02/44] Remove dead code --- .../graphics/src/graphics/BufferViewHelpers.h | 24 ------------------- 1 file changed, 24 deletions(-) diff --git a/libraries/graphics/src/graphics/BufferViewHelpers.h b/libraries/graphics/src/graphics/BufferViewHelpers.h index 8a48c17007..3635ef64e5 100644 --- a/libraries/graphics/src/graphics/BufferViewHelpers.h +++ b/libraries/graphics/src/graphics/BufferViewHelpers.h @@ -46,30 +46,6 @@ namespace buffer_helpers { gpu::BufferView clone(const gpu::BufferView& input); gpu::BufferView resized(const gpu::BufferView& input, glm::uint32 numElements); - inline void packNormalAndTangent(glm::vec3 normal, glm::vec3 tangent, glm::uint32& packedNormal, glm::uint32& packedTangent) { - auto absNormal = glm::abs(normal); - auto absTangent = glm::abs(tangent); - normal /= glm::max(1e-6f, glm::max(glm::max(absNormal.x, absNormal.y), absNormal.z)); - tangent /= glm::max(1e-6f, glm::max(glm::max(absTangent.x, absTangent.y), absTangent.z)); - normal = glm::clamp(normal, -1.0f, 1.0f); - tangent = glm::clamp(tangent, -1.0f, 1.0f); - normal *= 511.0f; - tangent *= 511.0f; - - glm::detail::i10i10i10i2 normalStruct; - glm::detail::i10i10i10i2 tangentStruct; - normalStruct.data.x = fastLrintf(normal.x); - normalStruct.data.y = fastLrintf(normal.y); - normalStruct.data.z = fastLrintf(normal.z); - normalStruct.data.w = 0; - tangentStruct.data.x = fastLrintf(tangent.x); - tangentStruct.data.y = fastLrintf(tangent.y); - tangentStruct.data.z = fastLrintf(tangent.z); - tangentStruct.data.w = 0; - packedNormal = normalStruct.pack; - packedTangent = tangentStruct.pack; - } - namespace mesh { glm::uint32 forEachVertex(const graphics::MeshPointer& mesh, std::function func); bool setVertexAttributes(const graphics::MeshPointer& mesh, glm::uint32 index, const QVariantMap& attributes); From 7236d63da0c544c4196095dcbeac151fcbb52de6 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Sat, 9 Feb 2019 12:16:26 -0800 Subject: [PATCH 03/44] Fix tabs --- libraries/shared/src/GLMHelpers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/shared/src/GLMHelpers.h b/libraries/shared/src/GLMHelpers.h index e50162d8a4..6deae695cd 100644 --- a/libraries/shared/src/GLMHelpers.h +++ b/libraries/shared/src/GLMHelpers.h @@ -322,7 +322,7 @@ inline void glm_mat4u_mul(const glm::mat4& m1, const glm::mat4& m2, glm::mat4& r // inline uint32_t glm_packSnorm3x10_1x2(vec4 const& v) { - union i10i10i10i2 { + union i10i10i10i2 { struct { int x : 10; int y : 10; From e46b9479131bd6ffa1840ced1de938918b14797d Mon Sep 17 00:00:00 2001 From: David Back Date: Fri, 15 Feb 2019 15:31:11 -0800 Subject: [PATCH 04/44] properly disable draggable numbers, fix disable script and collision sound --- scripts/system/html/js/entityProperties.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index c1a8f363b5..32b576c1f5 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -1485,6 +1485,8 @@ const ENTITY_SCRIPT_STATUS = { unloaded: "Unloaded" }; +const ENABLE_DISABLE_SELECTOR = "input, textarea, span, .dropdown dl, .color-picker"; + const PROPERTY_NAME_DIVISION = { GROUP: 0, PROPERTY: 1, @@ -1584,8 +1586,7 @@ function disableChildren(el, selector) { } function enableProperties() { - enableChildren(document.getElementById("properties-list"), - "input, textarea, checkbox, .dropdown dl, .color-picker , .draggable-number.text"); + enableChildren(document.getElementById("properties-list"), ENABLE_DISABLE_SELECTOR); enableChildren(document, ".colpick"); let elLocked = getPropertyInputElement("locked"); @@ -1596,8 +1597,7 @@ function enableProperties() { } function disableProperties() { - disableChildren(document.getElementById("properties-list"), - "input, textarea, checkbox, .dropdown dl, .color-picker, .draggable-number.text"); + disableChildren(document.getElementById("properties-list"), ENABLE_DISABLE_SELECTOR); disableChildren(document, ".colpick"); for (let pickKey in colorPickers) { colorPickers[pickKey].colpickHide(); @@ -3349,8 +3349,8 @@ function loaded() { let shouldHide = selectedEntityProperties.certificateID !== ""; if (shouldHide) { propertyValue = "** Certified **"; + property.elInput.disabled = true; } - property.elInput.disabled = shouldHide; } let isPropertyNotNumber = false; From 59a1e92dd8641aa630c0dc7106449ca66eeae573 Mon Sep 17 00:00:00 2001 From: David Back Date: Fri, 15 Feb 2019 16:25:04 -0800 Subject: [PATCH 05/44] fix git ignore for avatar exporter --- .gitignore | 9 +++------ tools/unity-avatar-exporter/Assets/Editor.meta | 8 -------- .../Assets/Editor/AvatarExporter.cs.meta | 11 ----------- tools/unity-avatar-exporter/Assets/README.txt.meta | 7 ------- 4 files changed, 3 insertions(+), 32 deletions(-) delete mode 100644 tools/unity-avatar-exporter/Assets/Editor.meta delete mode 100644 tools/unity-avatar-exporter/Assets/Editor/AvatarExporter.cs.meta delete mode 100644 tools/unity-avatar-exporter/Assets/README.txt.meta diff --git a/.gitignore b/.gitignore index 5a965b494c..e8527bbaf4 100644 --- a/.gitignore +++ b/.gitignore @@ -98,12 +98,9 @@ tools/jsdoc/package-lock.json # Python compile artifacts **/__pycache__ -# ignore unneeded unity project files for avatar exporter -tools/unity-avatar-exporter/Library -tools/unity-avatar-exporter/Logs -tools/unity-avatar-exporter/Packages -tools/unity-avatar-exporter/ProjectSettings -tools/unity-avatar-exporter/Temp +# ignore local unity project files for avatar exporter +tools/unity-avatar-exporter + server-console/package-lock.json vcpkg/ /tools/nitpick/compiledResources diff --git a/tools/unity-avatar-exporter/Assets/Editor.meta b/tools/unity-avatar-exporter/Assets/Editor.meta deleted file mode 100644 index cf7dcf12dd..0000000000 --- a/tools/unity-avatar-exporter/Assets/Editor.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 02111c50e71dd664da8ad5c6a6eca767 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter.cs.meta b/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter.cs.meta deleted file mode 100644 index 373aecc6a8..0000000000 --- a/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 00403fdc52187214c8418bc0a7f387e2 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/tools/unity-avatar-exporter/Assets/README.txt.meta b/tools/unity-avatar-exporter/Assets/README.txt.meta deleted file mode 100644 index 148fd21fdd..0000000000 --- a/tools/unity-avatar-exporter/Assets/README.txt.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 30b2b6221fd08234eb07c4d6d525d32e -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: From d7c2231f336e7a4045332ed6900251f1c63cac2c Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 20 Feb 2019 10:19:44 -0800 Subject: [PATCH 06/44] use root bone name from skeleton list --- .../Assets/Editor/AvatarExporter.cs | 26 ++++++++++++------ tools/unity-avatar-exporter/Assets/README.txt | 2 +- .../avatarExporter.unitypackage | Bin 13667 -> 13822 bytes 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter.cs b/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter.cs index 7b90145223..65ba0312a6 100644 --- a/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter.cs +++ b/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter.cs @@ -14,7 +14,7 @@ using System.Collections.Generic; class AvatarExporter : MonoBehaviour { // update version number for every PR that changes this file, also set updated version in README file - static readonly string AVATAR_EXPORTER_VERSION = "0.2"; + static readonly string AVATAR_EXPORTER_VERSION = "0.3"; static readonly float HIPS_GROUND_MIN_Y = 0.01f; static readonly float HIPS_SPINE_CHEST_MIN_SEPARATION = 0.001f; @@ -264,7 +264,7 @@ class AvatarExporter : MonoBehaviour { static string assetName = ""; static HumanDescription humanDescription; static Dictionary dependencyTextures = new Dictionary(); - + [MenuItem("High Fidelity/Export New Avatar")] static void ExportNewAvatar() { ExportSelectedAvatar(false); @@ -302,11 +302,11 @@ class AvatarExporter : MonoBehaviour { " the Rig section of it's Inspector window.", "Ok"); return; } - + humanDescription = modelImporter.humanDescription; SetUserBoneInformation(); string textureWarnings = SetTextureDependencies(); - + // check if we should be substituting a bone for a missing UpperChest mapping AdjustUpperChestMapping(); @@ -334,7 +334,7 @@ class AvatarExporter : MonoBehaviour { EditorUtility.DisplayDialog("Error", boneErrors, "Ok"); return; } - + string documentsFolder = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments); string hifiFolder = documentsFolder + "\\High Fidelity Projects"; if (updateAvatar) { // Update Existing Avatar menu option @@ -630,12 +630,14 @@ class AvatarExporter : MonoBehaviour { string boneName = modelBone.name; if (modelBone.parent == null) { // if no parent then this is actual root bone node of the user avatar, so consider it's parent as "root" + boneName = GetRootBoneName(); // ensure we use the root bone name from the skeleton list for consistency userBoneTree = new BoneTreeNode(boneName); // initialize root of tree userBoneInfo.parentName = "root"; userBoneInfo.boneTreeNode = userBoneTree; } else { // otherwise add this bone node as a child to it's parent's children list - string parentName = modelBone.parent.name; + // if its a child of the root bone, use the root bone name from the skeleton list as the parent for consistency + string parentName = modelBone.parent.parent == null ? GetRootBoneName() : modelBone.parent.name; BoneTreeNode boneTreeNode = new BoneTreeNode(boneName); userBoneInfos[parentName].boneTreeNode.children.Add(boneTreeNode); userBoneInfo.parentName = parentName; @@ -658,7 +660,7 @@ class AvatarExporter : MonoBehaviour { } return result; } - + static void AdjustUpperChestMapping() { if (!humanoidToUserBoneMappings.ContainsKey("UpperChest")) { // if parent of Neck is not Chest then map the parent to UpperChest @@ -682,6 +684,14 @@ class AvatarExporter : MonoBehaviour { } } + static string GetRootBoneName() { + // the "root" bone is the first element in the human skeleton bone list + if (humanDescription.skeleton.Length > 0) { + return humanDescription.skeleton[0].name; + } + return ""; + } + static void SetFailedBoneRules() { failedBoneRules.Clear(); @@ -901,7 +911,7 @@ class AvatarExporter : MonoBehaviour { textureDirectory = textureDirectory.Replace("\\\\", "\\"); return textureDirectory; } - + static string SetTextureDependencies() { string textureWarnings = ""; dependencyTextures.Clear(); diff --git a/tools/unity-avatar-exporter/Assets/README.txt b/tools/unity-avatar-exporter/Assets/README.txt index b81a620406..6516e4b150 100644 --- a/tools/unity-avatar-exporter/Assets/README.txt +++ b/tools/unity-avatar-exporter/Assets/README.txt @@ -1,6 +1,6 @@ High Fidelity, Inc. Avatar Exporter -Version 0.2 +Version 0.3 Note: It is recommended to use Unity versions between 2017.4.17f1 and 2018.2.12f1 for this Avatar Exporter. diff --git a/tools/unity-avatar-exporter/avatarExporter.unitypackage b/tools/unity-avatar-exporter/avatarExporter.unitypackage index 95c000e7c61b7623e0da0a1f9974e0744375014e..4c1474631204788903d573f18fc418d9c8cb1027 100644 GIT binary patch literal 13822 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 As{jB1 literal 13667 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 B&65BC From 36c66f019d1fcf79bdf7a49b90f789470da293b3 Mon Sep 17 00:00:00 2001 From: ingerjm0 Date: Sat, 23 Feb 2019 21:10:40 -0800 Subject: [PATCH 07/44] Add @signal tag to jsdoc; use custom jsdoc templates --- tools/jsdoc/config.json | 13 + tools/jsdoc/hifi-jsdoc-template/LICENSE.md | 61 ++ tools/jsdoc/hifi-jsdoc-template/README.md | 42 + tools/jsdoc/hifi-jsdoc-template/package.json | 59 ++ tools/jsdoc/hifi-jsdoc-template/publish.js | 772 ++++++++++++++++++ .../static/fonts/Cairo-Bold.ttf | Bin 0 -> 170996 bytes .../static/fonts/proximanova-regular.otf | Bin 0 -> 62892 bytes .../static/images/white-logo.png | Bin 0 -> 31280 bytes .../static/scripts/collapse.js | 11 + .../static/scripts/jquery-3.1.1.min.js | 4 + .../static/scripts/linenumber.js | 25 + .../scripts/prettify/Apache-License-2.0.txt | 202 +++++ .../static/scripts/prettify/lang-css.js | 2 + .../static/scripts/prettify/prettify.js | 28 + .../static/scripts/search.js | 42 + .../static/styles/jsdoc.css | 731 +++++++++++++++++ .../static/styles/prettify.css | 132 +++ .../hifi-jsdoc-template/tmpl/augments.tmpl | 10 + .../hifi-jsdoc-template/tmpl/container.tmpl | 283 +++++++ .../hifi-jsdoc-template/tmpl/details.tmpl | 143 ++++ .../hifi-jsdoc-template/tmpl/example.tmpl | 141 ++++ .../hifi-jsdoc-template/tmpl/examples.tmpl | 13 + .../hifi-jsdoc-template/tmpl/exceptions.tmpl | 32 + .../hifi-jsdoc-template/tmpl/layout.tmpl | 73 ++ .../hifi-jsdoc-template/tmpl/mainpage.tmpl | 10 + .../hifi-jsdoc-template/tmpl/members.tmpl | 41 + .../hifi-jsdoc-template/tmpl/method.tmpl | 119 +++ .../hifi-jsdoc-template/tmpl/methodList.tmpl | 107 +++ .../hifi-jsdoc-template/tmpl/paramList.tmpl | 67 ++ .../hifi-jsdoc-template/tmpl/params.tmpl | 115 +++ .../hifi-jsdoc-template/tmpl/properties.tmpl | 103 +++ .../hifi-jsdoc-template/tmpl/returns.tmpl | 8 + .../hifi-jsdoc-template/tmpl/returnsSimp.tmpl | 6 + .../hifi-jsdoc-template/tmpl/signal.tmpl | 123 +++ .../hifi-jsdoc-template/tmpl/signalList.tmpl | 92 +++ .../hifi-jsdoc-template/tmpl/source.tmpl | 8 + .../hifi-jsdoc-template/tmpl/tutorial.tmpl | 19 + .../jsdoc/hifi-jsdoc-template/tmpl/type.tmpl | 7 + tools/jsdoc/plugins/hifi.js | 35 +- 39 files changed, 3664 insertions(+), 15 deletions(-) create mode 100644 tools/jsdoc/hifi-jsdoc-template/LICENSE.md create mode 100644 tools/jsdoc/hifi-jsdoc-template/README.md create mode 100644 tools/jsdoc/hifi-jsdoc-template/package.json create mode 100644 tools/jsdoc/hifi-jsdoc-template/publish.js create mode 100644 tools/jsdoc/hifi-jsdoc-template/static/fonts/Cairo-Bold.ttf create mode 100644 tools/jsdoc/hifi-jsdoc-template/static/fonts/proximanova-regular.otf create mode 100644 tools/jsdoc/hifi-jsdoc-template/static/images/white-logo.png create mode 100644 tools/jsdoc/hifi-jsdoc-template/static/scripts/collapse.js create mode 100644 tools/jsdoc/hifi-jsdoc-template/static/scripts/jquery-3.1.1.min.js create mode 100644 tools/jsdoc/hifi-jsdoc-template/static/scripts/linenumber.js create mode 100644 tools/jsdoc/hifi-jsdoc-template/static/scripts/prettify/Apache-License-2.0.txt create mode 100644 tools/jsdoc/hifi-jsdoc-template/static/scripts/prettify/lang-css.js create mode 100644 tools/jsdoc/hifi-jsdoc-template/static/scripts/prettify/prettify.js create mode 100644 tools/jsdoc/hifi-jsdoc-template/static/scripts/search.js create mode 100644 tools/jsdoc/hifi-jsdoc-template/static/styles/jsdoc.css create mode 100644 tools/jsdoc/hifi-jsdoc-template/static/styles/prettify.css create mode 100644 tools/jsdoc/hifi-jsdoc-template/tmpl/augments.tmpl create mode 100644 tools/jsdoc/hifi-jsdoc-template/tmpl/container.tmpl create mode 100644 tools/jsdoc/hifi-jsdoc-template/tmpl/details.tmpl create mode 100644 tools/jsdoc/hifi-jsdoc-template/tmpl/example.tmpl create mode 100644 tools/jsdoc/hifi-jsdoc-template/tmpl/examples.tmpl create mode 100644 tools/jsdoc/hifi-jsdoc-template/tmpl/exceptions.tmpl create mode 100644 tools/jsdoc/hifi-jsdoc-template/tmpl/layout.tmpl create mode 100644 tools/jsdoc/hifi-jsdoc-template/tmpl/mainpage.tmpl create mode 100644 tools/jsdoc/hifi-jsdoc-template/tmpl/members.tmpl create mode 100644 tools/jsdoc/hifi-jsdoc-template/tmpl/method.tmpl create mode 100644 tools/jsdoc/hifi-jsdoc-template/tmpl/methodList.tmpl create mode 100644 tools/jsdoc/hifi-jsdoc-template/tmpl/paramList.tmpl create mode 100644 tools/jsdoc/hifi-jsdoc-template/tmpl/params.tmpl create mode 100644 tools/jsdoc/hifi-jsdoc-template/tmpl/properties.tmpl create mode 100644 tools/jsdoc/hifi-jsdoc-template/tmpl/returns.tmpl create mode 100644 tools/jsdoc/hifi-jsdoc-template/tmpl/returnsSimp.tmpl create mode 100644 tools/jsdoc/hifi-jsdoc-template/tmpl/signal.tmpl create mode 100644 tools/jsdoc/hifi-jsdoc-template/tmpl/signalList.tmpl create mode 100644 tools/jsdoc/hifi-jsdoc-template/tmpl/source.tmpl create mode 100644 tools/jsdoc/hifi-jsdoc-template/tmpl/tutorial.tmpl create mode 100644 tools/jsdoc/hifi-jsdoc-template/tmpl/type.tmpl diff --git a/tools/jsdoc/config.json b/tools/jsdoc/config.json index a24e248661..5074362225 100644 --- a/tools/jsdoc/config.json +++ b/tools/jsdoc/config.json @@ -1,4 +1,17 @@ { + "opts": { + "template": "hifi-jsdoc-template" + }, + "docdash": { + "meta": { + "title": "", + "description": "", + "keyword": "" + }, + "search": [true], + "collapse": [true], + "typedefs": [false] + }, "templates": { "default": { "outputSourceFiles": false diff --git a/tools/jsdoc/hifi-jsdoc-template/LICENSE.md b/tools/jsdoc/hifi-jsdoc-template/LICENSE.md new file mode 100644 index 0000000000..ff66af581b --- /dev/null +++ b/tools/jsdoc/hifi-jsdoc-template/LICENSE.md @@ -0,0 +1,61 @@ +# License + +Docdash is free software, licensed under the Apache License, Version 2.0 (the +"License"). Commercial and non-commercial use are permitted in compliance with +the License. + +Copyright (c) 2016 Clement Moron and the +[contributors to docdash](https://github.com/clenemt/docdash/graphs/contributors). +All rights reserved. + +You may obtain a copy of the License at: +http://www.apache.org/licenses/LICENSE-2.0 + +In addition, a copy of the License is included with this distribution. + +As stated in Section 7, "Disclaimer of Warranty," of the License: + +> Licensor provides the Work (and each Contributor provides its Contributions) +> on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +> express or implied, including, without limitation, any warranties or +> conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A +> PARTICULAR PURPOSE. You are solely responsible for determining the +> appropriateness of using or redistributing the Work and assume any risks +> associated with Your exercise of permissions under this License. + +The source code for docdash is available at: +https://github.com/clenemt/docdash + +# Third-Party Software + +Docdash includes or depends upon the following third-party software, either in +whole or in part. Each third-party software package is provided under its own +license. + +## JSDoc 3 + +JSDoc 3 is free software, licensed under the Apache License, Version 2.0 (the +"License"). Commercial and non-commercial use are permitted in compliance with +the License. + +Copyright (c) 2011-2016 Michael Mathews and the +[contributors to JSDoc](https://github.com/jsdoc3/jsdoc/graphs/contributors). +All rights reserved. + +You may obtain a copy of the License at: +http://www.apache.org/licenses/LICENSE-2.0 + +In addition, a copy of the License is included with this distribution. + +As stated in Section 7, "Disclaimer of Warranty," of the License: + +> Licensor provides the Work (and each Contributor provides its Contributions) +> on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +> express or implied, including, without limitation, any warranties or +> conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A +> PARTICULAR PURPOSE. You are solely responsible for determining the +> appropriateness of using or redistributing the Work and assume any risks +> associated with Your exercise of permissions under this License. + +The source code for JSDoc 3 is available at: +https://github.com/jsdoc3/jsdoc diff --git a/tools/jsdoc/hifi-jsdoc-template/README.md b/tools/jsdoc/hifi-jsdoc-template/README.md new file mode 100644 index 0000000000..797beaa79a --- /dev/null +++ b/tools/jsdoc/hifi-jsdoc-template/README.md @@ -0,0 +1,42 @@ +# hifi-jsdoc-template +The hifi-jsdoc-template is based on the [DocDash](https://github.com/clenemt/docdash) template. + +## Usage +Clone repository to your designated `jsdoc/node_modules` template directory. + +In your `config.json` file, add a template option. + +```json +"opts": { + "template": "node_modules/hifi-jsdoc-template" +} +``` + +## Sample `config.json` + +```json +{ + "opts": { + "template": "node_modules/hifi-jsdoc-template" + }, + "docdash": { + "meta": { + "title": "", + "description": "", + "keyword": "" + }, + "search": [true], + "collapse": [true], + "typedefs": [false] + }, + "templates": { + "default": { + "outputSourceFiles": false + } + }, + "plugins": [ + "plugins/hifi", + "plugins/hifiJSONExport" + ] +} +``` diff --git a/tools/jsdoc/hifi-jsdoc-template/package.json b/tools/jsdoc/hifi-jsdoc-template/package.json new file mode 100644 index 0000000000..f011adc2ba --- /dev/null +++ b/tools/jsdoc/hifi-jsdoc-template/package.json @@ -0,0 +1,59 @@ +{ + "_from": "docdash", + "_id": "docdash@1.0.0", + "_inBundle": false, + "_integrity": "sha512-HhK72PT4z55og8FDqskO/tTYXxU+LovRz+9pCDHLnUoPchkxjdIJidS+96LqW3CLrRdBmnkDRrcVrDFGLIluTw==", + "_location": "/docdash", + "_phantomChildren": {}, + "_requested": { + "type": "tag", + "registry": true, + "raw": "docdash", + "name": "docdash", + "escapedName": "docdash", + "rawSpec": "", + "saveSpec": null, + "fetchSpec": "latest" + }, + "_requiredBy": [ + "#USER", + "/" + ], + "_resolved": "https://registry.npmjs.org/docdash/-/docdash-1.0.0.tgz", + "_shasum": "5b7df10fed3d341fc4416a8978c65ad561869d18", + "_spec": "docdash", + "_where": "D:\\hifi\\tools\\jsdoc", + "author": { + "name": "Clement Moron", + "email": "clement.moron@gmail.com" + }, + "bugs": { + "url": "https://github.com/clenemt/docdash/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "A clean, responsive documentation template theme for JSDoc 3 inspired by lodash and minami", + "devDependencies": { + "browser-sync": "latest", + "jsdoc": "latest", + "watch-run": "latest" + }, + "homepage": "https://github.com/clenemt/docdash#readme", + "keywords": [ + "jsdoc", + "template" + ], + "license": "Apache-2.0", + "main": "publish.js", + "name": "docdash", + "repository": { + "type": "git", + "url": "git+https://github.com/clenemt/docdash.git" + }, + "scripts": { + "sync": "browser-sync start -s ../fixtures-doc -f ../fixtures-doc --reload-delay 1000 --no-ui --no-notify", + "test": "jsdoc -c fixtures/fixtures.conf.json", + "watch": "watch-run -d 1000 -p tmpl/**,static/** \"npm run test\"" + }, + "version": "1.0.0" +} diff --git a/tools/jsdoc/hifi-jsdoc-template/publish.js b/tools/jsdoc/hifi-jsdoc-template/publish.js new file mode 100644 index 0000000000..9cd428bbbb --- /dev/null +++ b/tools/jsdoc/hifi-jsdoc-template/publish.js @@ -0,0 +1,772 @@ +/*global env: true */ +'use strict'; + +var doop = require('jsdoc/util/doop'); +var fs = require('jsdoc/fs'); +var helper = require('jsdoc/util/templateHelper'); +var logger = require('jsdoc/util/logger'); +var path = require('jsdoc/path'); +var taffy = require('taffydb').taffy; +var template = require('jsdoc/template'); +var util = require('util'); + +var htmlsafe = helper.htmlsafe; +var linkto = helper.linkto; +var resolveAuthorLinks = helper.resolveAuthorLinks; +var scopeToPunc = helper.scopeToPunc; +var hasOwnProp = Object.prototype.hasOwnProperty; + +var data; +var view; + +var outdir = path.normalize(env.opts.destination); + +function copyFile(source, target, cb) { + var cbCalled = false; + + var rd = fs.createReadStream(source); + rd.on("error", function(err) { + done(err); + }); + var wr = fs.createWriteStream(target); + wr.on("error", function(err) { + done(err); + }); + wr.on("close", function(ex) { + done(); + }); + rd.pipe(wr); + + function done(err) { + if (!cbCalled) { + cb(err); + cbCalled = true; + } + } +} + +function find(spec) { + return helper.find(data, spec); +} + +function tutoriallink(tutorial) { + return helper.toTutorial(tutorial, null, { tag: 'em', classname: 'disabled', prefix: 'Tutorial: ' }); +} + +function getAncestorLinks(doclet) { + return helper.getAncestorLinks(data, doclet); +} + +function hashToLink(doclet, hash) { + if ( !/^(#.+)/.test(hash) ) { return hash; } + + var url = helper.createLink(doclet); + + url = url.replace(/(#.+|$)/, hash); + return '' + hash + ''; +} + +function needsSignature(doclet) { + var needsSig = false; + + // function and class definitions always get a signature + if (doclet.kind === 'function' || doclet.kind === 'class' && !doclet.hideconstructor) { + needsSig = true; + } + // typedefs that contain functions get a signature, too + else if (doclet.kind === 'typedef' && doclet.type && doclet.type.names && + doclet.type.names.length) { + for (var i = 0, l = doclet.type.names.length; i < l; i++) { + if (doclet.type.names[i].toLowerCase() === 'function') { + needsSig = true; + break; + } + } + } + + return needsSig; +} + +function getSignatureAttributes(item) { + var attributes = []; + + if (item.optional) { + attributes.push('opt'); + } + + if (item.nullable === true) { + attributes.push('nullable'); + } + else if (item.nullable === false) { + attributes.push('non-null'); + } + + return attributes; +} + +function updateItemName(item) { + var attributes = getSignatureAttributes(item); + var itemName = item.name || ''; + + if (item.variable) { + itemName = '…' + itemName; + } + + if (attributes && attributes.length) { + itemName = util.format( '%s%s', itemName, + attributes.join(', ') ); + } + + return itemName; +} + +function addParamAttributes(params) { + return params.filter(function(param) { + return param.name && param.name.indexOf('.') === -1; + }).map(updateItemName); +} + +function buildItemTypeStrings(item) { + var types = []; + + if (item && item.type && item.type.names) { + item.type.names.forEach(function(name) { + types.push( linkto(name, htmlsafe(name)) ); + }); + } + + return types; +} + +function buildAttribsString(attribs) { + var attribsString = ''; + + if (attribs && attribs.length) { + attribsString = htmlsafe( util.format('(%s) ', attribs.join(', ')) ); + } + + return attribsString; +} + +function addNonParamAttributes(items) { + var types = []; + + items.forEach(function(item) { + types = types.concat( buildItemTypeStrings(item) ); + }); + + return types; +} + +function addSignatureParams(f) { + var params = f.params ? addParamAttributes(f.params) : []; + f.signature = util.format( '%s( %s )', (f.signature || ''), params.join(', ') ); +} + +function addSignatureReturns(f) { + var attribs = []; + var attribsString = ''; + var returnTypes = []; + var returnTypesString = ''; + + // jam all the return-type attributes into an array. this could create odd results (for example, + // if there are both nullable and non-nullable return types), but let's assume that most people + // who use multiple @return tags aren't using Closure Compiler type annotations, and vice-versa. + if (f.returns) { + f.returns.forEach(function(item) { + helper.getAttribs(item).forEach(function(attrib) { + if (attribs.indexOf(attrib) === -1) { + attribs.push(attrib); + } + }); + }); + + attribsString = buildAttribsString(attribs); + } + + if (f.returns) { + returnTypes = addNonParamAttributes(f.returns); + } + if (returnTypes.length) { + returnTypesString = util.format( ' → %s{%s}', attribsString, returnTypes.join('|') ); + } + + f.signature = '' + (f.signature || '') + '' + + '' + returnTypesString + ''; +} + +function addSignatureTypes(f) { + var types = f.type ? buildItemTypeStrings(f) : []; + + f.signature = (f.signature || '') + '' + + (types.length ? ' :' + types.join('|') : '') + ''; +} + +function addAttribs(f) { + var attribs = helper.getAttribs(f); + var attribsString = buildAttribsString(attribs); + + f.attribs = util.format('%s', attribsString); +} + +function shortenPaths(files, commonPrefix) { + Object.keys(files).forEach(function(file) { + files[file].shortened = files[file].resolved.replace(commonPrefix, '') + // always use forward slashes + .replace(/\\/g, '/'); + }); + + return files; +} + +function getPathFromDoclet(doclet) { + if (!doclet.meta) { + return null; + } + + return doclet.meta.path && doclet.meta.path !== 'null' ? + path.join(doclet.meta.path, doclet.meta.filename) : + doclet.meta.filename; +} + +function generate(type, title, docs, filename, resolveLinks) { + resolveLinks = resolveLinks === false ? false : true; + + var docData = { + type: type, + title: title, + docs: docs + }; + + var outpath = path.join(outdir, filename), + html = view.render('container.tmpl', docData); + + if (resolveLinks) { + html = helper.resolveLinks(html); // turn {@link foo} into foo + } + + fs.writeFileSync(outpath, html, 'utf8'); +} + +function generateSourceFiles(sourceFiles, encoding) { + encoding = encoding || 'utf8'; + Object.keys(sourceFiles).forEach(function(file) { + var source; + // links are keyed to the shortened path in each doclet's `meta.shortpath` property + var sourceOutfile = helper.getUniqueFilename(sourceFiles[file].shortened); + helper.registerLink(sourceFiles[file].shortened, sourceOutfile); + + try { + source = { + kind: 'source', + code: helper.htmlsafe( fs.readFileSync(sourceFiles[file].resolved, encoding) ) + }; + } + catch(e) { + logger.error('Error while generating source file %s: %s', file, e.message); + } + + generate('Source', sourceFiles[file].shortened, [source], sourceOutfile, false); + }); +} + +/** + * Look for classes or functions with the same name as modules (which indicates that the module + * exports only that class or function), then attach the classes or functions to the `module` + * property of the appropriate module doclets. The name of each class or function is also updated + * for display purposes. This function mutates the original arrays. + * + * @private + * @param {Array.} doclets - The array of classes and functions to + * check. + * @param {Array.} modules - The array of module doclets to search. + */ +function attachModuleSymbols(doclets, modules) { + var symbols = {}; + + // build a lookup table + doclets.forEach(function(symbol) { + symbols[symbol.longname] = symbols[symbol.longname] || []; + symbols[symbol.longname].push(symbol); + }); + + return modules.map(function(module) { + if (symbols[module.longname]) { + module.modules = symbols[module.longname] + // Only show symbols that have a description. Make an exception for classes, because + // we want to show the constructor-signature heading no matter what. + .filter(function(symbol) { + return symbol.description || symbol.kind === 'class'; + }) + .map(function(symbol) { + symbol = doop(symbol); + + if (symbol.kind === 'class' || symbol.kind === 'function' && !symbol.hideconstructor) { + symbol.name = symbol.name.replace('module:', '(require("') + '"))'; + } + + return symbol; + }); + } + }); +} + +function buildMemberNav(items, itemHeading, itemsSeen, linktoFn) { + var nav = ''; + + if (items && items.length) { + var itemsNav = ''; + + items.forEach(function(item) { + var displayName; + var methods = find({kind:'function', memberof: item.longname}); + var signals = find({kind:'signal', memberof: item.longname}); + var members = find({kind:'member', memberof: item.longname}); + var docdash = env && env.conf && env.conf.docdash || {}; + var conf = env && env.conf || {}; + if ( !hasOwnProp.call(item, 'longname') ) { + itemsNav += '
  • ' + linktoFn('', item.name); + itemsNav += '
  • '; + } else if ( !hasOwnProp.call(itemsSeen, item.longname) ) { + if (conf.templates.default.useLongnameInNav) { + displayName = item.longname; + } else { + displayName = item.name; + } + itemsNav += '
  • ' + linktoFn(item.longname, displayName.replace(/\b(module|event):/g, '')); + + if (docdash.static && members.find(function (m) { return m.scope === 'static'; } )) { + itemsNav += "
      "; + + members.forEach(function (member) { + if (!member.scope === 'static') return; + itemsNav += "
    • '; + } + } + + return nav; +} + +function linktoTutorial(longName, name) { + return tutoriallink(name); +} + +function linktoExternal(longName, name) { + return linkto(longName, name.replace(/(^"|"$)/g, '')); +} + +/** + * Create the navigation sidebar. + * @param {object} members The members that will be used to create the sidebar. + * @param {array} members.classes + * @param {array} members.externals + * @param {array} members.globals + * @param {array} members.mixins + * @param {array} members.modules + * @param {array} members.namespaces + * @param {array} members.tutorials + * @param {array} members.events + * @param {array} members.interfaces + * @return {s + ring} The HTML for the navigation sidebar. + */ + +function buildNav(members) { + var nav = '

      Home

      '; + var seen = {}; + var seenTutorials = {}; + var docdash = env && env.conf && env.conf.docdash || {}; + if(docdash.menu){ + for(var menu in docdash.menu){ + nav += '

      '; + } + } + var defaultOrder = [ + 'Namespaces', 'Classes', 'Modules', 'Externals', 'Events', 'Mixins', 'Tutorials', 'Interfaces' + ]; + var order = docdash.sectionOrder || defaultOrder; + var sections = { + Namespaces: buildMemberNav(members.namespaces, 'Namespaces', seen, linkto), + Classes: buildMemberNav(members.classes, 'Classes', seen, linkto), + Modules: buildMemberNav(members.modules, 'Modules', {}, linkto), + Externals: buildMemberNav(members.externals, 'Externals', seen, linktoExternal), + Events: buildMemberNav(members.events, 'Events', seen, linkto), + Mixins: buildMemberNav(members.mixins, 'Mixins', seen, linkto), + Tutorials: buildMemberNav(members.tutorials, 'Tutorials', seenTutorials, linktoTutorial), + Interfaces: buildMemberNav(members.interfaces, 'Interfaces', seen, linkto), + }; + order.forEach(member => nav += sections[member]); + + if (members.globals.length) { + var globalNav = ''; + + members.globals.forEach(function(g) { + if ( (docdash.typedefs || g.kind !== 'typedef') && !hasOwnProp.call(seen, g.longname) ) { + globalNav += '
    • ' + linkto(g.longname, g.name) + '
    • '; + } + seen[g.longname] = true; + }); + + if (!globalNav) { + // turn the heading into a link so you can actually get to the global page + nav += '

      ' + linkto('global', 'Global') + '

      '; + } + else { + nav += '

      Globals

        ' + globalNav + '
      '; + } + } + + return nav; +} + +/** + @param {TAFFY} taffyData See . + @param {object} opts + @param {Tutorial} tutorials + */ +exports.publish = function(taffyData, opts, tutorials) { + var docdash = env && env.conf && env.conf.docdash || {}; + data = taffyData; + + var conf = env.conf.templates || {}; + conf.default = conf.default || {}; + + var templatePath = path.normalize(opts.template); + view = new template.Template( path.join(templatePath, 'tmpl') ); + + // claim some special filenames in advance, so the All-Powerful Overseer of Filename Uniqueness + // doesn't try to hand them out later + var indexUrl = helper.getUniqueFilename('index'); + // don't call registerLink() on this one! 'index' is also a valid longname + + var globalUrl = helper.getUniqueFilename('global'); + helper.registerLink('global', globalUrl); + + // set up templating + view.layout = conf.default.layoutFile ? + path.getResourcePath(path.dirname(conf.default.layoutFile), + path.basename(conf.default.layoutFile) ) : + 'layout.tmpl'; + + // set up tutorials for helper + helper.setTutorials(tutorials); + + data = helper.prune(data); + + docdash.sort !== false && data.sort('longname, version, since'); + helper.addEventListeners(data); + + var sourceFiles = {}; + var sourceFilePaths = []; + data().each(function(doclet) { + if(docdash.removeQuotes){ + if(docdash.removeQuotes === "all"){ + if(doclet.name){ + doclet.name = doclet.name.replace(/"/g, ''); + doclet.name = doclet.name.replace(/'/g, ''); + } + if(doclet.longname){ + doclet.longname = doclet.longname.replace(/"/g, ''); + doclet.longname = doclet.longname.replace(/'/g, ''); + } + } + else if(docdash.removeQuotes === "trim"){ + if(doclet.name){ + doclet.name = doclet.name.replace(/^"(.*)"$/, '$1'); + doclet.name = doclet.name.replace(/^'(.*)'$/, '$1'); + } + if(doclet.longname){ + doclet.longname = doclet.longname.replace(/^"(.*)"$/, '$1'); + doclet.longname = doclet.longname.replace(/^'(.*)'$/, '$1'); + } + } + } + doclet.attribs = ''; + + if (doclet.examples) { + doclet.examples = doclet.examples.map(function(example) { + var caption, code; + + if (example && example.match(/^\s*([\s\S]+?)<\/caption>(\s*[\n\r])([\s\S]+)$/i)) { + caption = RegExp.$1; + code = RegExp.$3; + } + + return { + caption: caption || '', + code: code || example || '' + }; + }); + } + if (doclet.see) { + doclet.see.forEach(function(seeItem, i) { + doclet.see[i] = hashToLink(doclet, seeItem); + }); + } + + // build a list of source files + var sourcePath; + if (doclet.meta) { + sourcePath = getPathFromDoclet(doclet); + sourceFiles[sourcePath] = { + resolved: sourcePath, + shortened: null + }; + if (sourceFilePaths.indexOf(sourcePath) === -1) { + sourceFilePaths.push(sourcePath); + } + } + }); + + // update outdir if necessary, then create outdir + var packageInfo = ( find({kind: 'package'}) || [] ) [0]; + if (packageInfo && packageInfo.name) { + outdir = path.join( outdir, packageInfo.name, (packageInfo.version || '') ); + } + fs.mkPath(outdir); + + // copy the template's static files to outdir + var fromDir = path.join(templatePath, 'static'); + var staticFiles = fs.ls(fromDir, 3); + + staticFiles.forEach(function(fileName) { + var toDir = fs.toDir( fileName.replace(fromDir, outdir) ); + fs.mkPath(toDir); + copyFile(fileName, path.join(toDir, path.basename(fileName)), function(err){if(err) console.err(err);}); + }); + + // copy user-specified static files to outdir + var staticFilePaths; + var staticFileFilter; + var staticFileScanner; + if (conf.default.staticFiles) { + // The canonical property name is `include`. We accept `paths` for backwards compatibility + // with a bug in JSDoc 3.2.x. + staticFilePaths = conf.default.staticFiles.include || + conf.default.staticFiles.paths || + []; + staticFileFilter = new (require('jsdoc/src/filter')).Filter(conf.default.staticFiles); + staticFileScanner = new (require('jsdoc/src/scanner')).Scanner(); + + staticFilePaths.forEach(function(filePath) { + var extraStaticFiles = staticFileScanner.scan([filePath], 10, staticFileFilter); + + extraStaticFiles.forEach(function(fileName) { + var sourcePath = fs.toDir(filePath); + var toDir = fs.toDir( fileName.replace(sourcePath, outdir) ); + fs.mkPath(toDir); + copyFile(fileName, path.join(toDir, path.basename(fileName)), function(err){if(err) console.err(err);}); + }); + }); + } + + if (sourceFilePaths.length) { + sourceFiles = shortenPaths( sourceFiles, path.commonPrefix(sourceFilePaths) ); + } + data().each(function(doclet) { + var url = helper.createLink(doclet); + helper.registerLink(doclet.longname, url); + + // add a shortened version of the full path + var docletPath; + if (doclet.meta) { + docletPath = getPathFromDoclet(doclet); + docletPath = sourceFiles[docletPath].shortened; + if (docletPath) { + doclet.meta.shortpath = docletPath; + } + } + }); + + data().each(function(doclet) { + var url = helper.longnameToUrl[doclet.longname]; + + if (url.indexOf('#') > -1) { + doclet.id = helper.longnameToUrl[doclet.longname].split(/#/).pop(); + } + else { + doclet.id = doclet.name; + } + + if ( needsSignature(doclet) ) { + addSignatureParams(doclet); + addSignatureReturns(doclet); + addAttribs(doclet); + } + }); + + // do this after the urls have all been generated + data().each(function(doclet) { + doclet.ancestors = getAncestorLinks(doclet); + + if (doclet.kind === 'member') { + addSignatureTypes(doclet); + addAttribs(doclet); + } + + if (doclet.kind === 'constant') { + addSignatureTypes(doclet); + addAttribs(doclet); + doclet.kind = 'member'; + } + }); + + var members = helper.getMembers(data); + members.tutorials = tutorials.children; + + // output pretty-printed source files by default + var outputSourceFiles = conf.default && conf.default.outputSourceFiles !== false + ? true + : false; + + // add template helpers + view.find = find; + view.linkto = linkto; + view.resolveAuthorLinks = resolveAuthorLinks; + view.tutoriallink = tutoriallink; + view.htmlsafe = htmlsafe; + view.outputSourceFiles = outputSourceFiles; + + // once for all + view.nav = buildNav(members); + attachModuleSymbols( find({ longname: {left: 'module:'} }), members.modules ); + + // generate the pretty-printed source files first so other pages can link to them + if (outputSourceFiles) { + generateSourceFiles(sourceFiles, opts.encoding); + } + + if (members.globals.length) { + generate('', 'Global', [{kind: 'globalobj'}], globalUrl); + } + + // index page displays information from package.json and lists files + var files = find({kind: 'file'}); + var packages = find({kind: 'package'}); + + generate('', 'High Fidelity API Reference', + packages.concat( + [{kind: 'mainpage', readme: opts.readme, longname: (opts.mainpagetitle) ? opts.mainpagetitle : 'Main Page'}] + ).concat(files), + indexUrl); + + // set up the lists that we'll use to generate pages + var classes = taffy(members.classes); + var modules = taffy(members.modules); + var namespaces = taffy(members.namespaces); + var mixins = taffy(members.mixins); + var externals = taffy(members.externals); + var interfaces = taffy(members.interfaces); + + Object.keys(helper.longnameToUrl).forEach(function(longname) { + var myModules = helper.find(modules, {longname: longname}); + if (myModules.length) { + generate('Module', myModules[0].name, myModules, helper.longnameToUrl[longname]); + } + + var myClasses = helper.find(classes, {longname: longname}); + if (myClasses.length) { + generate('Class', myClasses[0].name, myClasses, helper.longnameToUrl[longname]); + } + + var myNamespaces = helper.find(namespaces, {longname: longname}); + if (myNamespaces.length) { + generate('Namespace', myNamespaces[0].name, myNamespaces, helper.longnameToUrl[longname]); + } + + var myMixins = helper.find(mixins, {longname: longname}); + if (myMixins.length) { + generate('Mixin', myMixins[0].name, myMixins, helper.longnameToUrl[longname]); + } + + var myExternals = helper.find(externals, {longname: longname}); + if (myExternals.length) { + generate('External', myExternals[0].name, myExternals, helper.longnameToUrl[longname]); + } + + var myInterfaces = helper.find(interfaces, {longname: longname}); + if (myInterfaces.length) { + generate('Interface', myInterfaces[0].name, myInterfaces, helper.longnameToUrl[longname]); + } + }); + + // TODO: move the tutorial functions to templateHelper.js + function generateTutorial(title, tutorial, filename) { + var tutorialData = { + title: title, + header: tutorial.title, + content: tutorial.parse(), + children: tutorial.children + }; + + var tutorialPath = path.join(outdir, filename); + var html = view.render('tutorial.tmpl', tutorialData); + + // yes, you can use {@link} in tutorials too! + html = helper.resolveLinks(html); // turn {@link foo} into
      foo + fs.writeFileSync(tutorialPath, html, 'utf8'); + } + + // tutorials can have only one parent so there is no risk for loops + function saveChildren(node) { + node.children.forEach(function(child) { + generateTutorial('Tutorial: ' + child.title, child, helper.tutorialToUrl(child.name)); + saveChildren(child); + }); + } + + saveChildren(tutorials); +}; diff --git a/tools/jsdoc/hifi-jsdoc-template/static/fonts/Cairo-Bold.ttf b/tools/jsdoc/hifi-jsdoc-template/static/fonts/Cairo-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..ad884391d78a4c9012f51b6681746bb51cb7f7c0 GIT binary patch literal 170996 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 z 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�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 literal 0 HcmV?d00001 diff --git a/tools/jsdoc/hifi-jsdoc-template/static/fonts/proximanova-regular.otf b/tools/jsdoc/hifi-jsdoc-template/static/fonts/proximanova-regular.otf new file mode 100644 index 0000000000000000000000000000000000000000..27c8d8f7bf9e823f3d2b89ed8efaf401baf4b942 GIT binary patch literal 62892 zcmb@u30M@z)<0Z5Lr+6DG)g-}XVNpH0`4sCyC9-~Y_bT51_u}x9T*&723ItjNi;5r zCNW0ExQh#-C@O-A3$DQh+!2gMV@zTa!)b28^?SO92;TR;|8IG|@!{03PMtb+PIc9( zr8^0ajt)l*T8!k#+kfIj-3JvveTG&4CM zWS5g|%E^8G3F?B7;~9jI4iTbgw{LfsR~IHakNz9U<n+fw2I z8c2j9BtxV^E+%%15!xSt8t^}AGL1Po$QS9bovkgoE4r>j#QIRtfFEV+B@g5XAr&$9 zP5Z-a)=AV64Qu1e5QY5PupIS9!EM;CgA9p!A#)pFfjG3T4O3_U+S7&|kQ2Joh8d(r zKeb`U4!BbXot-w>xv1d=1d&H*8mMJU@afi%PiZCHj_VsjgoqX=Su8@59p#OpRp zqA;0z8&-7SQ)rqjr;YD`RI)2=m_b8jPus9#2iysDmGl0l?78NQwDeqE@8mwZP`!D! zE-E9_l$B%3>aQEFw<^D&3TuY|66ed_2892Mupi zAT}_dt^Qj&Gjeo#U9MT5V#pMYHl@C8yysi4r03>lkM#1gTCJX7WI|aeN22|a4h=-!$Quno zo=AuMkP#V?u7j2wDQ7@A$bihqf($4Hd7=npMkbUmY11Pe3PUDjkx(Q`Ly^dU(oh~U zO6~sB`hT`P66yYrdOGS5W&g4B?Y94EdBA_PI#sea2W3cp>W~leL_WwH`JhoK0!1O6 zBas*KLRRUY=NsLkXC0rUr(}8N|7xie3&nVdWL?@Kz`NoMlky5e zKnOV?Xe*JT<^O{pfn-RI>=20*h(hVe0nvy-j>rkI$QgA)oskRTP#2^`uIL@q6?H=@ zq(<)|9%+yk=}>pn1NB61$Q^m0UZ^+fgZiR=s6QHjJdv05SO%g&XfPUrhN59;I2wUQ zqETox8iU57amW`fK;w}=nt%e(L^KHnq97EECZiA(io#Ghia=9PB#J`OC?L*Ef9LXA?; zH^jRHPiP1&p+n2iN}@Yjg}y}d(Mc*eTp)W z75O21w2AOQKcaIendpUPBO}U0S!fP2qda6m^Uxl25EY?As1zMWM^G6$ijJdlqBp8Q zr_gD12CYVmPyt$umZ101hv*~pF5JHd8Vx&Mx(lbazGtnYch_;|T=r!R@ z_z=Ftcw!0>MI;h>!b;>53y1>Z3*xn`n@lY$mYtVfl0A^Gk?)e1%TMaM=u|q5u7}P; z=dBy58>^e3%ht`+73eCHT>CxFEwHMbwHuY{A))d+FUem0m ztxemTb~RNtRW&_mdfxPV(_c;hYHDqI4c);FJYWQjgL$wS%Ag5e3$L-=>(|oiD~_|7 zNRJB9X0#RUBM{+33?%#rezL_RT>SV(+9w8*;3RI*~(IoT!I?KeJhx~{r+ zbvnt%5p6!^>K5u2>ps_Q)@{*kmwa@6<6~6!gzl@_eC*sq*`wPVA5(gi{D+U7Bp>Z0 zABQ(ZH|d))B_E5Ls+#UMJ#6}=>19)M2Oqs*9Oxw<8$b|VWAys<>qg}Fx)Htmx)FW! zx>B0M5wB;WaDoq*#=ebx8s;~gYN%{D^3eJaH|&16@8S0iK@U|AH4mK; zst-e`9@qa}f3Lo*{_w+o^_}jIyYG45{oeHZ+`amHH}5UJd$apv<}|aGImnbS#mqit zFH^+qW_E~;(lT1k!?>{0ANq_%eeuNw0@qbs3co!j*hEh-=N<|-_ z-Dnw_g}z4H&|&sguX{VqUGodDQcZW572q^m^h0Tp-K9=H{7|ZgcsAfUgXb#FnKcT1SPl89=k(uZrn~gBh1-&5NLC**!dV*R|GvSJU zM$geNvZG?ulN}Rx>e4P6A@uqq@oexve+06VA%Y;f{Fhys$oCRDq2@}W`J}A*lw9a) zhr2n-H#yqjaX9r~SDSZ}@4A2O{I2`y&L??IiSu+g*=cC8j1XnKbnjp zP%KJ9X($Wjp}A-=`WStRmZOzuEn1H@qaCOOoj_MmJ$i*+6EvYFJP03RG!a5fBMgLz zm`{96d_im=iii@ToVZNfBVNkvWSwL>Ss$6VY^2Oj7AOmoMavRoNwRcVmTa!1o&Tf<4HoF6MC+w>1F4+BGS8LZ`_lwZ_(ri!aX?Y7s8U>1 z)GF!~PZfVC1d5;(lmpd`>Phvd22*3HNmK+CM@8>pRB2~|#=rD~{q z)DsHqkv(ItvhQW@Wk1~B&pyb0ihY88ihZVio_&G+r}kgiueaY~Uu0iuUtxdV{s;Rz z_CMOcum=aZgR_I$!NbAF!OtPWA;BTlVUEKBhh+|5J8W_&ayaa8&f%8BPYz8EuW6d@ zO!IUfdN4hKj-hALv*`u&NAxOsJ-vrMLSLY3=_m9{8Z(Z}JB%AMmibz~e>j(r_RIR-h#Ii@-0JAUT4!EwLiX~!#$w;g|UY;q!; zXeXr;@6_AL%W0%jfK!B1f>VZ**=e5B`%cT9);eu;+U`{Bbj+#Bsm7_!>Auq=r)N&T zIlXfF7mHX0>&UvWU0Dt5#`a~s*`e%cc03!%hOyD?G~i*N_ItL3J;7dL zYuWqk&+IGqwX?G`@7&vYkh8z@6z6#76lat3Jm=4x*E(-;-sgPO`Hb^T=SR-JIzuP2 zlYJ+rPA;8-I?d>0%rfN~=H%&(8Cj_rSsA%=jfR{YiIHYD=yMHb31{ogxfyz6N=9mG zPF`lFJ~zXZm2EbqfqxWF+g2`s{48DPO8P!C=hQXC>ui z>yr&e(>y~~njs+1Y|6{Z7&yphc&ew~nCp|8n3S5Bo|-t@C}s5$oh#8vZ8Rq{Iok%4 z%m$00BWy29Hf3h&^~uSGtX!KwN5&g5V~$aulP(Du^~rg;Hf6?+vZ7JOWWCvxB|&|= zm_E&{Z);wkoMBGR%S<&I@@-Nn83wZ@2cI_W>!pOj+CearcF^WOO0LFNrlZ|Kluhe}c>q?l}7 znQD79sfnqHHsoh>rOhKh$r+nVel~B~obs2HCri}7U3+pn^nYV_@*CtYb$+r$CrC7< z4Vz8++!Toh*eo#Ek^sp9gG2+~=rO!O0XC})wj@B(W{_xyeoSk($~Ml@Bz^6@mi9(p z$FY^xVeAC9t4ME$fk}FEdXnB8B#nv;i3ZsW&#)yyQcD>U4YC=TVM~JEv>6nfF)O%T z>8y4*xq}6>JK{96!H{LtXQgB$he*%BHsnJ($aEa}AySXnhJHwjDOY^{VN$&;iH3Ek zm(>A>N%gX9R4-l^noZg1hJdUzLsnY2%|nwd371?nNi;k?FDp%N&dW6F^KwlcGm%nr zW{F02Xvo|FM@r3^B^o73=14TEy>3z|oSvT!}^}>CL%G zdUK5Q!15#-V{;?Vmc&SY4xOlhLn^H zeWocZMaqd+dSXDEm6|v!+hER3H|6E%vr;@wS$UaKn9UWb4Q1tJ=2}gjQkrfy7$lTx z$}`(QhQ-Fo$;g)&IR=X%OF{Lf){=yz zrbHyQB>`JwB5Z3-gtq2Hlx#AZvPAv4dh=YVRdEHDK&sJX&d8ErR$gY3c*UA#%jV=7 z%tmqD5;e><*qCpdoswmetQJ$zXepI!7LjDK1VoEPAQ~*ClD#6bnJXg6S`kRyot2kq z7W+d?Ma@zwX%>;BSpuSF5r~?lRMIRWn`RM7nnhq+qoj4OZSk^U+f=k++w_sJZQ-&( zDHycDw^!Bn#Y-x-tyOJMT&g5!TbpdKT~+%kWh=1-6dTS;v!xwuYuosU%XWtqt1aJQ z<0A>Yi3(D-!yltVd z!MDdj`%XeC&DNU@Sz=K2OxEWZq?{CQrEHQ}pFG=;`=+=p|F(b>lHZ8iqP3JY%DLu>~HafpToNJ&)t1D@6n zZO%#pDJG*)ZtOH4)ju znuw&ZCW3$ZR%*siqT?m%FVP7SwV6Lr!jmK#DA6E^+NSW0CXRE8l6agPJcmvOK+kt)3x+H#*XRCXqX<%KxQa2gZYs8lv%}m#q4EHF;AqM zpm!WcI!<$(>1c4wbTm6!9KUqj>Ui4my5sLojMF<#1D!&h(wxjrR;QItYn+Olik;3m zU3a?g)aca2ICmQuZ5m7rU1&XDit=>`k_weayaK zU$M<>tFz46-r337#o5)_&Dq;|sPkxNKj$##1m|SubZ3)uuJdB&<<4I^Z*tz^T;zPf z`H1sz=Tpw-oUc0HaenOlyYs)CUw5)o9yV_=&9Pd{b2iM~qFK3m`EvCqS?1I%Ytfvp zB|D2MPN^7WA8;f675%XrS)sW1cYSw~xx>$)%gN-F=)5R(&yZU`eWVps8x`O_1Qgf< zYkFZ4>u|q6-M~!)ec*r+UsK#%S@GykHOP(+oUmNWz{3J1i~|xn!%!HCN$7l)$0Y8I zhvK0?;?6KmTVsbijrtinLFaqVpc8bu=ZQPxPNN3kPFhBdJ+K@|7zl$w4s!6gcij+E zs=ZQ5-k36?5;JNXi3eaFr{H85fVGTri~{$@ZsZvSqkIl-WSnAD_u+q&af)BD8_B?> z0wws|`w`yN!cU`dBh@D=)ZIP$!mk==9F2dXu=?&m@X;{X?XEKVue6H%wKHzn=Es!S&)B8t%nNp8In&%?jsSaUg6ZfBLfi3OK63dC(oq zYH(qzS3PV1l>)}#4J7UYKPj<4dyRvqxX5Jao0ZMuuO~J7qq`%UsbGOGG+$&A3ZTs6F->@J>8fHl$sGV zKk#IfAs}ho|LE;o*ODU-XlqKyTT@3=VOou&aX+lXdaQ?jSO?Ksra%eqKmG|6^yqUP zI}Y)iG9yd7X4#i(RPfGOcn4f-N=(UnHKiBG<4IGBhN^MIFgzRw;^6Ce7=&w=)+(`m z;-B>&YR~S!bm*$O;fEQ0LgL4`X;~!<0|X8bti?xyAX(9K(U@>gHFolP3NFAs{Ry0| zoXwoMUt4{MJQp{dY+7bdE?@N z(qat*KNl#=Xzb+q6gc3XJprdnXN?Jav={f0SEr9Z+DDB?VGcXsF?cL+n1)eWM%fs0 z#5XQ+mMLHJ+3IDhSE+6;-+S|}x^&BeoXy&urQ{A%>V{Y~c8DB+?Xdh#seYSF`X3yr5&Bf{yrP+~MR{1dG@WiC_dHMMoP{H(aybc?w!}H1QJ9d3t ztUgsdD}II{Ejq!lXxih3hrDkCQtxXRS$54~?GE zTbnv6=w8bZiYdp56wru$onZ>aPY+gT|u{+XY6MX3x^X z0=QG#(jQ~0+Cm;KtJru}{p4cQpphY=-XkN5&LnE%qR5~VH#7WJ(8+xBaPW4u~st}9oS9@t!7 zUYw`bFtxY|=E3i^_;;8MO|{HD?hLFdP(rVo8_%>{%_y2XgA?GVdaP4TGrZStOmOkR zRE<7@oK|)x^@W=2&6MLQ%BA0I{barR((>}{JFmgV!kw-o6?jOC4i6S|L zk-lNq94&k%Xvode)`W$raJQLQgE1#(^Z$?4^uWw2W=_B2Ot8m{y=Xy#1RE8?||7$i++Ym*lBu zi^B>|{(7YkbRCDgjtaVmYi`pw!~teg1%q(_7FE?Lm_j|xD9;|4&9G?UCm$@) zGQvw8%_xuK*9jC0eO=)>RkHcwfn(~g)_nHa8trW=D9R9@qGg0Rt~I!Uf;+-U@?6XK ziExL)cUnf05fszoQS|-GRo@>e(J-#?Gxcg}xySgRq@-CI_`t}O9JPY$n3hgd zVB(Ak3F%vR=V%O(##%qYGksMU*Nm51=* zX^=zVk@zq2s)GHZ-~x=Qg25M<>C0+hVhxO_Vb&K~z_A8et&Fntl;X!Pj+R|j-J7^M zc)bQ(sJ$QWp1(O~-@dNdyOK9Yud+X*kD^8`jh+#v8eNlrWxfV$sTr#c4D3*X+gRv{ zC*p}?aZl`qd)~%wFcBu+1~=%b8S1Kw?~Wa@WBlJuO(*^aM{p|duG6rt5C|mD;0@lG z1ViwfM>2|`y6S|9{jf}jmwRXfDHgT~P2`!D1V6wO-rVwpWR*Yzc>)G#g>2vP6tgRV&SZ|S z@VcR9_8y5p+SO!8w@Q^s{)7Z^oO&VtNY9RhS}Avsoz3*3*tf;adK`UP{7!qcavYZ>7? zSNtuM!pE?V?4!WT@eUGpjBYu07ec9%XTgYSi-u6{rEMNY)X6fv# zH-&#sD%@OWA#Hbjl%u?qLb@mOBk|3;`bF_^rn*t~~i{?*xa6yGw7Y8l+>MLt(BTlDek zqSSbt?KCmCXzZC-?aT=Bs$$c2lF2%7e14T0dOZaN=x&&=Bp%h4ogt$YxmhGr4%OuZ z6rGpD&rGZ^Mj4}MacMb5Rx17$#wcTFCnwC9b+A&yz&lDXQKj3??LV)6adwnWH)V9+ z@QA&obF|FjBLx=7IlX+%a>hy1?s&Owb@f0=T`^lvL9$1v79^xH;G$>M%gUj@M!4L`WfyLO|gr4whVI0nDFV*LsK<7L&(jgr5pCD z8Eh%E2*c_YTN&u_MOpx-dAb1k?0msrKQRA{6LMmPy>#4-kt!{fxW5q+=fc9k~Z00ZX=ln{Iq zCc{uh_yve1Gy}g|VEge8tS;xzGV}O53^WtF1ZO#85uVf%OhK)1pq4qnA7d&Sg@Q%~ zjuj}GL$~<*CGZymnaYinbP8wwE~rVf2uo@Ttc>y`)e;IOGK6CAH_iT5Vi}annOflw zE90`JxeG%e;z#rhpeq6L8_K& zuvgkow2!h+vNzkmZ@rW)?G-DPUGI+n7@374zD$r{f&Q0>>YmR8E^%j^)|$YzP~}CbA3J z)$C^WigPFD?#{u^3C=0bA3GO2pLWKbKJ2uj)3=?rcPi<0sne}a&pQd7sm`j-KAqz` zn>#P=yt;E~=OdjTyL5BOclq39m&-wyJ1&27dE683Wf%J{fn8>I$?USW%N3* zZcx@Kn_N9yy^of+?Bb(MAHyAJOf-E~gam0e4_z0++#H~(%ky5)6S-fc^_ z6WwaN{jG9Rd8o##rmON*pR0DLPO9#yK;2pGt)8ULQm<8?RzG{U%ez7Ee)I0Wch9_g z|J^@%mhZ<0@+tfpem8%Tzr+8gQD}N<{4|N0g_`x65>1WfiI&mwS}*MwZHP8ZyIy-r z=cJpiTdCWjYw13)`=svH?iYJF^icQc-@~uR%bxvuj_vtT&l_%TZrN_z-5$HWaQoY> z)tz*Ac7MnHUH6{up6cYzXyyPU>UG|K%HkVPhZb?&&{4&JnwqBd5!nddmZtr@p|Ib z;{A?yAMY^lH19Ru4}IKxM)`#Mr25SBS>v?$H%9(7%3)ORQDa9ILC1wZ$Y?ctm3yUKUJ?^QqA&&zLx-=E`y$ItP1@lWzU=HECWd&1R#DFL|wUj~#0)CN2Y zXqm`N)J*i5m^5+4!~+vwOtPQ!?xe|+Op}gHDxY+5(w#|9CPAPgP!-rS&@*sMU_ziV zupn?n;CF%h0xJV=1l9-s9Qd!GwZXFB;NT;ZM@(Kk`T68OCO3zmkWL}4A$*8i$bgVR zA;Uv_LnepBgrtU;LaZSLA)kh<4*4o%e@IoRCUjq7U3UJSh)`eUdN<`kw2 zOAq@t>_FJ%uovM}xJS4?e17;B;XA_5hd+(5i|7_HFd`(v5b=J*Hxc_IE<`j&yqZE! z={?1FO6-(5Qx;D-HKis}896?3Mr2Op^2m*mha!KEqN21>qoN|CGNKkmeHFDm>Tpz5 z)U~LGQNKntMg2RPj^?9#M-Pe)jE;-Wh@Ka{EP7k?!RWKmf5uFSNsO_?Y@6C|>XoVW zQ~!)5Vx42V#}1607&|3)dTeIw)!5r{!{YqnBI4rX=Ep6ID~v0OI~rFNR}(LbcaB%b zN5z-KSH?F_qo#4whEAI>ZQitxrY)aVmf)PwE5SD*J|RD0b;7QMd(#I^51c+@x_SDi z)7MQento#Xjp?=1f14qn(QSt3jEOT6XXMUUI%EBe{WGd(JbbVFd!yc)^4`Mt)=u-; z)%^V~;?8b3R3sPte3Z@g_^;M_3U2ID;zP~f!yyHWPq6sz5|9a(tS;w4Hsk_V10E2r zTrcF30~G69a>?B|Udc7=+PZD$XS9~Z>4GcVr!2!Ne2QU8hw9?H&Gw{nIdS3Ol|( zc)XhmJHN{K!=%AWsnKh~4jRhhCwDy&d0YSTBYTK|DawS|k^PrwAfLKsIg=f%!WZC% z^6ZJy>#H<)CN*i()Gen~EKDeg^`{qk?fdwp zlCz!^#x;A9QMUUC?)XW;yFmH;^7UuWg7?!}{8I2zM(E2gUMVdA{M!z1h%Qy(Q(j#72vZ~*370Afm~%!h%z{hGN*oQzkvJJg$3isDI0G3J zi|>B?iZ~xivv>^{t`NK6Lpgj82IUp}VGzaQJ4--DoCld4s3ppe=z9K~RS8R)W61~w zUeX#%vQ>3FA>H1|;anVzGw1Ozv0e`AT${a?(JiMbwrE+cu&tI5#ype@Ym(^Y1-t2; zyJ*;0(4YRi&;ny_3S+DU{829#CVWWmE!fLHs)qv)<#4KC7{9Ne77pBikXoYRA>4W> zhYOy3QeiC*8Lk=pwmROWavcvxdeQq97t!Sp;r2s0Y+me1DRD|xo%K&H5tt-7FMBQMiWHt}pEq@4ua zNkW(<^j4m137tv_p*W_Lj=W4m^#fjT!joH^a1a?nu>-`&vaHqxM%HHA1<$<=&BgEe3euvKunYQ7b^?{(R?@8u04V;}brUIi#?Z+w67f_CmUG9xA| zZ-N?+#E#$$gCSh{?}?_uSRgTjhht4ZV#*xL#yzW-uUWoYdj__UlN5_WN$&T<`HB02 z)tJT(*bZy^o)3C<>HL8c`?McY`V~bfRqBV2?}0b?V;AUwr{EMk1y96A8~|#}L$LNk zNK*!<9=r77*3ZA6+oLyrrOm=xQlAx&iN zUI{L)z+S)EbT8uOgs-%mQ2k9+)kD?q6Ru%<4L;H8rGWhctHje`HcVI49ZU!hOP=AY zU4_pmu^#4uUctS(Um6oOVMgLuEenndc%q_F2)!mBz_Z{cooR?W^@4k&Je_6}Y2r@3 zT=?2`2LExP11vlnJ4oZRviP7%H$F(Y2|o>hRgaX*q5loO zLFiI1Z>C)Xcy>Ka+~(!uXm)p@1vb>e7qt&)*Z`pvbi4Hw2q1i)VwF~W52k>x;AuS_ z>+2g6J6hXTQE(|x)?C<7bV7T1;+Yd6SIM&%_BQ^ef_SWk-qpN#g;33d3ipP1O|2d7 z+aK(~tL-il`nbInN%mL3 z=2kC~g?sb(ba&cVq=Hhs#ZR7}hU1NC`U%`>L=!56v zV8M}x=z1QOSe54#*cKPtioyMy9A@IkQXY3|_OcQi1&v(rfkq`B4Ufo31s;PRkrx!8 zh9XeoB9i^G|7k+F)L(hJ16%Abh6IYeEi|3pQ=|D?L1gi zXxP>DJ?Z4nM$j(hw_sHrw?K$&>%?JaOzE)YQs* z@GRb1#1p^N$zj}Jo}J5Yrn&puY3@Z|nq69$!-KDtxK#%$>*T_mNS?(H3yt*Smo67x z4yxl`ZsfUV#VzGZGtJ_MIPQYbYVA+pYdlpFR3yn0)v=Vi7a^aJBQFI<(S0{(Q z%Xt=7eJ8nOtb@!t?tb$eSNMZ^F}-|HK=6#jY|V*<`h(-u{*&X37A;qv$8+~fwpH#g zS6|wi5~juX>!67$*?Mx{3H8No5`$uw+Vriev#DYYSXsyA$I@Jx zH_zoyqS&Cz{0bpo4kfNIL$H!>zpk6nVkKFac$xpYIYFMqvmz3b<$}o-hrx32hXV0B zT8%@n3PQv?Xn$OQL-BI5Q338S4LtBPk`1!mQ4wM@V|exoO@z}dK8_>z&}YwfX@E~~ z0cy7^k`q0jOrPZqSpR8N@jRx3LxUVAP=!^q5zoy3@nz>)E z?V(^>hRoyfI3Z6C7Xx|rTA>BllTDS-X#FSRyb>c03oB0I6-}_B63?bM0j$vY_FF5k z;zknBidAs0V1*8^mK8sv9QJ-eK?FKV;4dfV=!r&WIME2n2>P0iK#ZwOd-PIY+e z-bb4?rx%{JMyl8h@ulnY<3y=Q<-$DRl~Gk>(ZLNTPN*v8o|s*tsXCLjBPxn4N{QPL zua1kKH!DROS!FU+MUt~q=EldV;y1(>C2OLhc4VD7L(VEWF}Ff}qGH3I5^Yr^X@)%I zfU#o-3>bU+=jXR?{rvOoas4$cZkA4OU(zfdDMr~-V1ESc<)?%#$}{}OAAb5-2@iu^ z&+tn>{Pfcjp2ZFqZ}P%`i#ar2ckw8FaTCo-0G0;x?DWE=Jot-Y?J|t(NpmG|%8%v_ zw1v0ng_n4UsNjZzpiW(UfF$+DE#9}5@%3@R*G=N z((YolzaM`>9;OB^B_V@)yp&||9f$Y{3w74^>p3KNJ_J5xiZW1?{JwU%CEF6YeS&huezJOT{c6isSb2P##R< z`YSwGQ#KO;cIh2I*EN&4h z#9Me`*+W|Xn^56Rv-qz%nt;J&@|QR&gx_|Bd{1E_*TJ{;XV`>_XEvN;Ah)*$iLRh*TNj-j};`|D)6=V zB78>ua+T;Xs_K4eAhzB+FhIp`h?}gt5EjPXN zA{nT#7)j2!n&IqEVPr&sqMpUwkVTgq*Q-8U-`>v z67R2ryVUbjYjRYUl-*^E6z)$yxu^`yP)yFcmg*YM!PdZ^|R=_|N+?tb2+T&2=4QeS#J?H4t4uCBSG zWpS+#ww4w~C@0XdLhqA=FzB>gm?g|mwuDXBc_H*Xw_Gyo zns9Xm&-HBy9i^N=zxV4?aH<4{r!G5%c)ax~_Y6)8Ta;TZo6Kg5)jX%rvUO`=;WiET z5(2SNS=kaFOL5O&8y=+jp*vU3T| z^?0mB0!cJn}&OeGkzURlCav@PLD1jdEvv?iS ze}G7z_Xh`{e|`=Qnk?5|BZhl;jHv(p&jD>eCuu8~UUc<36~Lm`hCs5%s}+ic`fBk`)GK)57*8H21O(%{?1NvtVAl z`{f>J-Shiy;>d15#e#LWyx9zoln{kI!4pT}NbH5B6uht(L_!pJf)_+;jIP)hcgH=j zANIvPpa=MZAM}9kQraDN$9@_dg;{0#oawmVB) zGg$IZ(Y>b)d`rgXJm)IpHm}ps+%v(kbzR45Ig&3}~Y!#Bg zq7&sqr3R|^h&7=9Wd80+`cA{1Bm9AS&O`8So;8T(E->1`<}j&XJzf6PrK0iq=lm~?Tz_GwWW)6{t=rlvJq8O* z5bMNAR@_|FR_pjlx}x#%5&m%_=OKjIj0kVF^q|>7`b*fbzme+=x4!4On}=KT`}6D^ z{=Pqb=OM6Q+4+#`Eqo!Gwx%`TpKmLvh7A>B!2;2=!M1{XPhIXjEcu*2@Q~{-d}_0- zs&(6&I=jFEPGY5@Hrp19)vmoquMu9g$iRa2^;~aZP9)8pIo4{7=C4f_HHw9?&%UYO z@Qmv#q)JN9{L;EEn%{YxhrzIc^M?BGdF~_>wHlSNJR3nz=gV*10!w@ymuI_TDxJb} zdC?SCI)vtE2yXUp|3~aA*pTzThii|=ghv*6j$Oq zgyx(U7Yd(yiyF_Jq|0y3Kf=HFzsfo+z9+01PIKg9ADVMme3%Z$Q%Y{{-gT3P+%h>F z##2K0^`*B~9pAIJtXuq1a^~zLYrNV$_+C@f<-32JI5ao0NPD7;Jf0f6e~=ox^~EyW z6RR7$gX>~#Uf57Rk*_YMpMm9*TJCudp6jwg80RkDuvHh++hN0&Hf|2=?=EsLKK;Kq zd-J#`j^=;7ch}j~UY#iI65X|Ty~QiweZ&LB;DMr`;(@my3Lc2EctZ@HcpKx1qJpB} z4T6Ax2Zu%x6;?rl8iR^SG>OSm!_({I@71#lnml=)&-45KF$~kw-P7A$UEN*vt}2JL zM_+HIJBmqVb4nZ|;c-)J%e@iI&+WNg;7l*Ou4uj;H0#e_Zd`>){*;eizIx#>>*YbqAwCuNkDw&K()!ECC4Ir%k{5JO!6ZN4R&d<` z{5%_%SOQb%f?{$#LRvHtlh}w*O0GxvQbLfse2mc|&galYygv|^R)RUIloYkZ#0k1q zHEu;ko*EC)an-4MX+twEf#biubk}COtCZYpiAe`&CtYfa69bW16@(Gru^dD6Nr*e){*!uJw*hBzJ{QByVu z%-8=?);k4@L(g!L9LobUDeOy$6TGgv(TY~f(O$i9*di^lHrY(&w;kYF)tshSyp4<8 z@J|p;vPWX#0zvX2i+M^8@f6<8phrWF&Gu__A|PYot#!3Iq+J)ZD0pI|5p>(J)g;w3 zOUJ?#aW_=ZUaGy7)}%bWp#rBW#Rh8aCUq}T#6M8|E_tn_)=pBlV#O(o3KY`BSUQN_ z#d$d}HkT}c07;?q_dgiB%mi&Tu?Nl_I%mi~KhfPpQor!?^)!+tpZV!7X-I0&(et6H zhVuLyzx_J$W{+upVRIImptqORT_dv1(wv)E>Z(i1R$tl{fA~a-J@W-4o$C0(S!E&_ zDPF7~2bO3^*^&K;M-mLl`xp9|nE!QHqB*kv)R6>3(g8U^BeKr-D0I&u58*klGD!37 zqKmyJP74lMY$T~Q)jT{BedfqHL-O&ZV@zza=I>9gtdRfI! WU`Gn&ro$r5k-bSr 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 literal 0 HcmV?d00001 diff --git a/tools/jsdoc/hifi-jsdoc-template/static/images/white-logo.png b/tools/jsdoc/hifi-jsdoc-template/static/images/white-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..18cd2d88ddc2816a0d7f4b8b8554943037094b8e GIT binary patch literal 31280 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 NqW-1x#kvlU{s*yk?ZW^7 literal 0 HcmV?d00001 diff --git a/tools/jsdoc/hifi-jsdoc-template/static/scripts/collapse.js b/tools/jsdoc/hifi-jsdoc-template/static/scripts/collapse.js new file mode 100644 index 0000000000..4525c1756e --- /dev/null +++ b/tools/jsdoc/hifi-jsdoc-template/static/scripts/collapse.js @@ -0,0 +1,11 @@ +function hideAllButCurrent(){ + //by default all submenut items are hidden + $("nav > ul > li > ul li").hide(); + + //only current page (if it exists) should be opened + var file = window.location.pathname.split("/").pop(); + $("nav > ul > li > a[href^='"+file+"']").parent().find("> ul li").show(); +} +$( document ).ready(function() { + hideAllButCurrent(); +}); \ No newline at end of file diff --git a/tools/jsdoc/hifi-jsdoc-template/static/scripts/jquery-3.1.1.min.js b/tools/jsdoc/hifi-jsdoc-template/static/scripts/jquery-3.1.1.min.js new file mode 100644 index 0000000000..4c5be4c0fb --- /dev/null +++ b/tools/jsdoc/hifi-jsdoc-template/static/scripts/jquery-3.1.1.min.js @@ -0,0 +1,4 @@ +/*! jQuery v3.1.1 | (c) jQuery Foundation | jquery.org/license */ +!function(a,b){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){"use strict";var c=[],d=a.document,e=Object.getPrototypeOf,f=c.slice,g=c.concat,h=c.push,i=c.indexOf,j={},k=j.toString,l=j.hasOwnProperty,m=l.toString,n=m.call(Object),o={};function p(a,b){b=b||d;var c=b.createElement("script");c.text=a,b.head.appendChild(c).parentNode.removeChild(c)}var q="3.1.1",r=function(a,b){return new r.fn.init(a,b)},s=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,t=/^-ms-/,u=/-([a-z])/g,v=function(a,b){return b.toUpperCase()};r.fn=r.prototype={jquery:q,constructor:r,length:0,toArray:function(){return f.call(this)},get:function(a){return null==a?f.call(this):a<0?this[a+this.length]:this[a]},pushStack:function(a){var b=r.merge(this.constructor(),a);return b.prevObject=this,b},each:function(a){return r.each(this,a)},map:function(a){return this.pushStack(r.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(f.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(a<0?b:0);return this.pushStack(c>=0&&c0&&b-1 in a)}var x=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=function(a,b){for(var c=0,d=a.length;c+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(N),U=new RegExp("^"+L+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L+"|[*])"),ATTR:new RegExp("^"+M),PSEUDO:new RegExp("^"+N),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),aa=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:d<0?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ba=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ca=function(a,b){return b?"\0"===a?"\ufffd":a.slice(0,-1)+"\\"+a.charCodeAt(a.length-1).toString(16)+" ":"\\"+a},da=function(){m()},ea=ta(function(a){return a.disabled===!0&&("form"in a||"label"in a)},{dir:"parentNode",next:"legend"});try{G.apply(D=H.call(v.childNodes),v.childNodes),D[v.childNodes.length].nodeType}catch(fa){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s=b&&b.ownerDocument,w=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==w&&9!==w&&11!==w)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==w&&(l=Z.exec(a)))if(f=l[1]){if(9===w){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(s&&(j=s.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(l[2])return G.apply(d,b.getElementsByTagName(a)),d;if((f=l[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==w)s=b,r=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(ba,ca):b.setAttribute("id",k=u),o=g(a),h=o.length;while(h--)o[h]="#"+k+" "+sa(o[h]);r=o.join(","),s=$.test(a)&&qa(b.parentNode)||b}if(r)try{return G.apply(d,s.querySelectorAll(r)),d}catch(x){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(P,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("fieldset");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&a.sourceIndex-b.sourceIndex;if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return function(b){return"form"in b?b.parentNode&&b.disabled===!1?"label"in b?"label"in b.parentNode?b.parentNode.disabled===a:b.disabled===a:b.isDisabled===a||b.isDisabled!==!a&&ea(b)===a:b.disabled===a:"label"in b&&b.disabled===a}}function pa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function qa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return!!b&&"HTML"!==b.nodeName},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),v!==n&&(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(n.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){return a.getAttribute("id")===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}}):(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c,d,e,f=b.getElementById(a);if(f){if(c=f.getAttributeNode("id"),c&&c.value===a)return[f];e=b.getElementsByName(a),d=0;while(f=e[d++])if(c=f.getAttributeNode("id"),c&&c.value===a)return[f]}return[]}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){if("undefined"!=typeof b.getElementsByClassName&&p)return b.getElementsByClassName(a)},r=[],q=[],(c.qsa=Y.test(n.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){a.innerHTML="";var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+K+"*[*^$|!~]?="),2!==a.querySelectorAll(":enabled").length&&q.push(":enabled",":disabled"),o.appendChild(a).disabled=!0,2!==a.querySelectorAll(":disabled").length&&q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Y.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"*"),s.call(a,"[s!='']:x"),r.push("!=",N)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Y.test(o.compareDocumentPosition),t=b||Y.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?I(k,a)-I(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?I(k,a)-I(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?la(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(S,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.escape=function(a){return(a+"").replace(ba,ca)},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(_,aa),a[3]=(a[3]||a[4]||a[5]||"").replace(_,aa),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return V.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&T.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(_,aa).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:!b||(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(O," ")+" ").indexOf(c)>-1:"|="===b&&(e===c||e.slice(0,c.length+1)===c+"-"))}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(P,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(_,aa),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return U.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(_,aa).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:oa(!1),disabled:oa(!0),checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:pa(function(){return[0]}),last:pa(function(a,b){return[b-1]}),eq:pa(function(a,b,c){return[c<0?c+b:c]}),even:pa(function(a,b){for(var c=0;c=0;)a.push(d);return a}),gt:pa(function(a,b,c){for(var d=c<0?c+b:c;++d1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function va(a,b,c){for(var d=0,e=b.length;d-1&&(f[j]=!(g[j]=l))}}else r=wa(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ya(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ta(function(a){return a===b},h,!0),l=ta(function(a){return I(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];i1&&ua(m),i>1&&sa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(P,"$1"),c,i0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=E.call(i));u=wa(u)}G.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&ga.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=ya(b[c]),f[u]?d.push(f):e.push(f);f=A(a,za(e,d)),f.selector=a}return f},i=ga.select=function(a,b,c,e){var f,i,j,k,l,m="function"==typeof a&&a,n=!e&&g(a=m.selector||a);if(c=c||[],1===n.length){if(i=n[0]=n[0].slice(0),i.length>2&&"ID"===(j=i[0]).type&&9===b.nodeType&&p&&d.relative[i[1].type]){if(b=(d.find.ID(j.matches[0].replace(_,aa),b)||[])[0],!b)return c;m&&(b=b.parentNode),a=a.slice(i.shift().value.length)}f=V.needsContext.test(a)?0:i.length;while(f--){if(j=i[f],d.relative[k=j.type])break;if((l=d.find[k])&&(e=l(j.matches[0].replace(_,aa),$.test(i[0].type)&&qa(b.parentNode)||b))){if(i.splice(f,1),a=e.length&&sa(i),!a)return G.apply(c,e),c;break}}}return(m||h(a,n))(e,b,!p,c,!b||$.test(a)&&qa(b.parentNode)||b),c},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("fieldset"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){if(!c)return a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){if(!c&&"input"===a.nodeName.toLowerCase())return a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(J,function(a,b,c){var d;if(!c)return a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);r.find=x,r.expr=x.selectors,r.expr[":"]=r.expr.pseudos,r.uniqueSort=r.unique=x.uniqueSort,r.text=x.getText,r.isXMLDoc=x.isXML,r.contains=x.contains,r.escapeSelector=x.escape;var y=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&r(a).is(c))break;d.push(a)}return d},z=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},A=r.expr.match.needsContext,B=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i,C=/^.[^:#\[\.,]*$/;function D(a,b,c){return r.isFunction(b)?r.grep(a,function(a,d){return!!b.call(a,d,a)!==c}):b.nodeType?r.grep(a,function(a){return a===b!==c}):"string"!=typeof b?r.grep(a,function(a){return i.call(b,a)>-1!==c}):C.test(b)?r.filter(b,a,c):(b=r.filter(b,a),r.grep(a,function(a){return i.call(b,a)>-1!==c&&1===a.nodeType}))}r.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?r.find.matchesSelector(d,a)?[d]:[]:r.find.matches(a,r.grep(b,function(a){return 1===a.nodeType}))},r.fn.extend({find:function(a){var b,c,d=this.length,e=this;if("string"!=typeof a)return this.pushStack(r(a).filter(function(){for(b=0;b1?r.uniqueSort(c):c},filter:function(a){return this.pushStack(D(this,a||[],!1))},not:function(a){return this.pushStack(D(this,a||[],!0))},is:function(a){return!!D(this,"string"==typeof a&&A.test(a)?r(a):a||[],!1).length}});var E,F=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,G=r.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||E,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:F.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof r?b[0]:b,r.merge(this,r.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),B.test(e[1])&&r.isPlainObject(b))for(e in b)r.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&(this[0]=f,this.length=1),this}return a.nodeType?(this[0]=a,this.length=1,this):r.isFunction(a)?void 0!==c.ready?c.ready(a):a(r):r.makeArray(a,this)};G.prototype=r.fn,E=r(d);var H=/^(?:parents|prev(?:Until|All))/,I={children:!0,contents:!0,next:!0,prev:!0};r.fn.extend({has:function(a){var b=r(a,this),c=b.length;return this.filter(function(){for(var a=0;a-1:1===c.nodeType&&r.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?r.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?i.call(r(a),this[0]):i.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(r.uniqueSort(r.merge(this.get(),r(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function J(a,b){while((a=a[b])&&1!==a.nodeType);return a}r.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return y(a,"parentNode")},parentsUntil:function(a,b,c){return y(a,"parentNode",c)},next:function(a){return J(a,"nextSibling")},prev:function(a){return J(a,"previousSibling")},nextAll:function(a){return y(a,"nextSibling")},prevAll:function(a){return y(a,"previousSibling")},nextUntil:function(a,b,c){return y(a,"nextSibling",c)},prevUntil:function(a,b,c){return y(a,"previousSibling",c)},siblings:function(a){return z((a.parentNode||{}).firstChild,a)},children:function(a){return z(a.firstChild)},contents:function(a){return a.contentDocument||r.merge([],a.childNodes)}},function(a,b){r.fn[a]=function(c,d){var e=r.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=r.filter(d,e)),this.length>1&&(I[a]||r.uniqueSort(e),H.test(a)&&e.reverse()),this.pushStack(e)}});var K=/[^\x20\t\r\n\f]+/g;function L(a){var b={};return r.each(a.match(K)||[],function(a,c){b[c]=!0}),b}r.Callbacks=function(a){a="string"==typeof a?L(a):r.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),c<=h&&h--}),this},has:function(a){return a?r.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||b||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j};function M(a){return a}function N(a){throw a}function O(a,b,c){var d;try{a&&r.isFunction(d=a.promise)?d.call(a).done(b).fail(c):a&&r.isFunction(d=a.then)?d.call(a,b,c):b.call(void 0,a)}catch(a){c.call(void 0,a)}}r.extend({Deferred:function(b){var c=[["notify","progress",r.Callbacks("memory"),r.Callbacks("memory"),2],["resolve","done",r.Callbacks("once memory"),r.Callbacks("once memory"),0,"resolved"],["reject","fail",r.Callbacks("once memory"),r.Callbacks("once memory"),1,"rejected"]],d="pending",e={state:function(){return d},always:function(){return f.done(arguments).fail(arguments),this},"catch":function(a){return e.then(null,a)},pipe:function(){var a=arguments;return r.Deferred(function(b){r.each(c,function(c,d){var e=r.isFunction(a[d[4]])&&a[d[4]];f[d[1]](function(){var a=e&&e.apply(this,arguments);a&&r.isFunction(a.promise)?a.promise().progress(b.notify).done(b.resolve).fail(b.reject):b[d[0]+"With"](this,e?[a]:arguments)})}),a=null}).promise()},then:function(b,d,e){var f=0;function g(b,c,d,e){return function(){var h=this,i=arguments,j=function(){var a,j;if(!(b=f&&(d!==N&&(h=void 0,i=[a]),c.rejectWith(h,i))}};b?k():(r.Deferred.getStackHook&&(k.stackTrace=r.Deferred.getStackHook()),a.setTimeout(k))}}return r.Deferred(function(a){c[0][3].add(g(0,a,r.isFunction(e)?e:M,a.notifyWith)),c[1][3].add(g(0,a,r.isFunction(b)?b:M)),c[2][3].add(g(0,a,r.isFunction(d)?d:N))}).promise()},promise:function(a){return null!=a?r.extend(a,e):e}},f={};return r.each(c,function(a,b){var g=b[2],h=b[5];e[b[1]]=g.add,h&&g.add(function(){d=h},c[3-a][2].disable,c[0][2].lock),g.add(b[3].fire),f[b[0]]=function(){return f[b[0]+"With"](this===f?void 0:this,arguments),this},f[b[0]+"With"]=g.fireWith}),e.promise(f),b&&b.call(f,f),f},when:function(a){var b=arguments.length,c=b,d=Array(c),e=f.call(arguments),g=r.Deferred(),h=function(a){return function(c){d[a]=this,e[a]=arguments.length>1?f.call(arguments):c,--b||g.resolveWith(d,e)}};if(b<=1&&(O(a,g.done(h(c)).resolve,g.reject),"pending"===g.state()||r.isFunction(e[c]&&e[c].then)))return g.then();while(c--)O(e[c],h(c),g.reject);return g.promise()}});var P=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;r.Deferred.exceptionHook=function(b,c){a.console&&a.console.warn&&b&&P.test(b.name)&&a.console.warn("jQuery.Deferred exception: "+b.message,b.stack,c)},r.readyException=function(b){a.setTimeout(function(){throw b})};var Q=r.Deferred();r.fn.ready=function(a){return Q.then(a)["catch"](function(a){r.readyException(a)}),this},r.extend({isReady:!1,readyWait:1,holdReady:function(a){a?r.readyWait++:r.ready(!0)},ready:function(a){(a===!0?--r.readyWait:r.isReady)||(r.isReady=!0,a!==!0&&--r.readyWait>0||Q.resolveWith(d,[r]))}}),r.ready.then=Q.then;function R(){d.removeEventListener("DOMContentLoaded",R), +a.removeEventListener("load",R),r.ready()}"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(r.ready):(d.addEventListener("DOMContentLoaded",R),a.addEventListener("load",R));var S=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===r.type(c)){e=!0;for(h in c)S(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,r.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(r(a),c)})),b))for(;h1,null,!0)},removeData:function(a){return this.each(function(){W.remove(this,a)})}}),r.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=V.get(a,b),c&&(!d||r.isArray(c)?d=V.access(a,b,r.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=r.queue(a,b),d=c.length,e=c.shift(),f=r._queueHooks(a,b),g=function(){r.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return V.get(a,c)||V.access(a,c,{empty:r.Callbacks("once memory").add(function(){V.remove(a,[b+"queue",c])})})}}),r.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length\x20\t\r\n\f]+)/i,ka=/^$|\/(?:java|ecma)script/i,la={option:[1,""],thead:[1,"","
      "],col:[2,"","
      "],tr:[2,"","
      "],td:[3,"","
      "],_default:[0,"",""]};la.optgroup=la.option,la.tbody=la.tfoot=la.colgroup=la.caption=la.thead,la.th=la.td;function ma(a,b){var c;return c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[],void 0===b||b&&r.nodeName(a,b)?r.merge([a],c):c}function na(a,b){for(var c=0,d=a.length;c-1)e&&e.push(f);else if(j=r.contains(f.ownerDocument,f),g=ma(l.appendChild(f),"script"),j&&na(g),c){k=0;while(f=g[k++])ka.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),o.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="",o.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var qa=d.documentElement,ra=/^key/,sa=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,ta=/^([^.]*)(?:\.(.+)|)/;function ua(){return!0}function va(){return!1}function wa(){try{return d.activeElement}catch(a){}}function xa(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)xa(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=va;else if(!e)return a;return 1===f&&(g=e,e=function(a){return r().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=r.guid++)),a.each(function(){r.event.add(this,b,e,d,c)})}r.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=V.get(a);if(q){c.handler&&(f=c,c=f.handler,e=f.selector),e&&r.find.matchesSelector(qa,e),c.guid||(c.guid=r.guid++),(i=q.events)||(i=q.events={}),(g=q.handle)||(g=q.handle=function(b){return"undefined"!=typeof r&&r.event.triggered!==b.type?r.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(K)||[""],j=b.length;while(j--)h=ta.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n&&(l=r.event.special[n]||{},n=(e?l.delegateType:l.bindType)||n,l=r.event.special[n]||{},k=r.extend({type:n,origType:p,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&r.expr.match.needsContext.test(e),namespace:o.join(".")},f),(m=i[n])||(m=i[n]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,o,g)!==!1||a.addEventListener&&a.addEventListener(n,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),r.event.global[n]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=V.hasData(a)&&V.get(a);if(q&&(i=q.events)){b=(b||"").match(K)||[""],j=b.length;while(j--)if(h=ta.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n){l=r.event.special[n]||{},n=(d?l.delegateType:l.bindType)||n,m=i[n]||[],h=h[2]&&new RegExp("(^|\\.)"+o.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&p!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,o,q.handle)!==!1||r.removeEvent(a,n,q.handle),delete i[n])}else for(n in i)r.event.remove(a,n+b[j],c,d,!0);r.isEmptyObject(i)&&V.remove(a,"handle events")}},dispatch:function(a){var b=r.event.fix(a),c,d,e,f,g,h,i=new Array(arguments.length),j=(V.get(this,"events")||{})[b.type]||[],k=r.event.special[b.type]||{};for(i[0]=b,c=1;c=1))for(;j!==this;j=j.parentNode||this)if(1===j.nodeType&&("click"!==a.type||j.disabled!==!0)){for(f=[],g={},c=0;c-1:r.find(e,this,null,[j]).length),g[e]&&f.push(d);f.length&&h.push({elem:j,handlers:f})}return j=this,i\x20\t\r\n\f]*)[^>]*)\/>/gi,za=/\s*$/g;function Da(a,b){return r.nodeName(a,"table")&&r.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a:a}function Ea(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function Fa(a){var b=Ba.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Ga(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(V.hasData(a)&&(f=V.access(a),g=V.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;c1&&"string"==typeof q&&!o.checkClone&&Aa.test(q))return a.each(function(e){var f=a.eq(e);s&&(b[0]=q.call(this,e,f.html())),Ia(f,b,c,d)});if(m&&(e=pa(b,a[0].ownerDocument,!1,a,d),f=e.firstChild,1===e.childNodes.length&&(e=f),f||d)){for(h=r.map(ma(e,"script"),Ea),i=h.length;l")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=r.contains(a.ownerDocument,a);if(!(o.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||r.isXMLDoc(a)))for(g=ma(h),f=ma(a),d=0,e=f.length;d0&&na(g,!i&&ma(a,"script")),h},cleanData:function(a){for(var b,c,d,e=r.event.special,f=0;void 0!==(c=a[f]);f++)if(T(c)){if(b=c[V.expando]){if(b.events)for(d in b.events)e[d]?r.event.remove(c,d):r.removeEvent(c,d,b.handle);c[V.expando]=void 0}c[W.expando]&&(c[W.expando]=void 0)}}}),r.fn.extend({detach:function(a){return Ja(this,a,!0)},remove:function(a){return Ja(this,a)},text:function(a){return S(this,function(a){return void 0===a?r.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return Ia(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Da(this,a);b.appendChild(a)}})},prepend:function(){return Ia(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Da(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ia(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ia(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(r.cleanData(ma(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null!=a&&a,b=null==b?a:b,this.map(function(){return r.clone(this,a,b)})},html:function(a){return S(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!za.test(a)&&!la[(ja.exec(a)||["",""])[1].toLowerCase()]){a=r.htmlPrefilter(a);try{for(;c1)}});function Ya(a,b,c,d,e){return new Ya.prototype.init(a,b,c,d,e)}r.Tween=Ya,Ya.prototype={constructor:Ya,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||r.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(r.cssNumber[c]?"":"px")},cur:function(){var a=Ya.propHooks[this.prop];return a&&a.get?a.get(this):Ya.propHooks._default.get(this)},run:function(a){var b,c=Ya.propHooks[this.prop];return this.options.duration?this.pos=b=r.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Ya.propHooks._default.set(this),this}},Ya.prototype.init.prototype=Ya.prototype,Ya.propHooks={_default:{get:function(a){var b;return 1!==a.elem.nodeType||null!=a.elem[a.prop]&&null==a.elem.style[a.prop]?a.elem[a.prop]:(b=r.css(a.elem,a.prop,""),b&&"auto"!==b?b:0)},set:function(a){r.fx.step[a.prop]?r.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[r.cssProps[a.prop]]&&!r.cssHooks[a.prop]?a.elem[a.prop]=a.now:r.style(a.elem,a.prop,a.now+a.unit)}}},Ya.propHooks.scrollTop=Ya.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},r.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:"swing"},r.fx=Ya.prototype.init,r.fx.step={};var Za,$a,_a=/^(?:toggle|show|hide)$/,ab=/queueHooks$/;function bb(){$a&&(a.requestAnimationFrame(bb),r.fx.tick())}function cb(){return a.setTimeout(function(){Za=void 0}),Za=r.now()}function db(a,b){var c,d=0,e={height:a};for(b=b?1:0;d<4;d+=2-b)c=ba[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function eb(a,b,c){for(var d,e=(hb.tweeners[b]||[]).concat(hb.tweeners["*"]),f=0,g=e.length;f1)},removeAttr:function(a){return this.each(function(){r.removeAttr(this,a)})}}),r.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?r.prop(a,b,c):(1===f&&r.isXMLDoc(a)||(e=r.attrHooks[b.toLowerCase()]||(r.expr.match.bool.test(b)?ib:void 0)), +void 0!==c?null===c?void r.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=r.find.attr(a,b),null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!o.radioValue&&"radio"===b&&r.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d=0,e=b&&b.match(K);if(e&&1===a.nodeType)while(c=e[d++])a.removeAttribute(c)}}),ib={set:function(a,b,c){return b===!1?r.removeAttr(a,c):a.setAttribute(c,c),c}},r.each(r.expr.match.bool.source.match(/\w+/g),function(a,b){var c=jb[b]||r.find.attr;jb[b]=function(a,b,d){var e,f,g=b.toLowerCase();return d||(f=jb[g],jb[g]=e,e=null!=c(a,b,d)?g:null,jb[g]=f),e}});var kb=/^(?:input|select|textarea|button)$/i,lb=/^(?:a|area)$/i;r.fn.extend({prop:function(a,b){return S(this,r.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[r.propFix[a]||a]})}}),r.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&r.isXMLDoc(a)||(b=r.propFix[b]||b,e=r.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=r.find.attr(a,"tabindex");return b?parseInt(b,10):kb.test(a.nodeName)||lb.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),o.optSelected||(r.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),r.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){r.propFix[this.toLowerCase()]=this});function mb(a){var b=a.match(K)||[];return b.join(" ")}function nb(a){return a.getAttribute&&a.getAttribute("class")||""}r.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).addClass(a.call(this,b,nb(this)))});if("string"==typeof a&&a){b=a.match(K)||[];while(c=this[i++])if(e=nb(c),d=1===c.nodeType&&" "+mb(e)+" "){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=mb(d),e!==h&&c.setAttribute("class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).removeClass(a.call(this,b,nb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(K)||[];while(c=this[i++])if(e=nb(c),d=1===c.nodeType&&" "+mb(e)+" "){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=mb(d),e!==h&&c.setAttribute("class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):r.isFunction(a)?this.each(function(c){r(this).toggleClass(a.call(this,c,nb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=r(this),f=a.match(K)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=nb(this),b&&V.set(this,"__className__",b),this.setAttribute&&this.setAttribute("class",b||a===!1?"":V.get(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+mb(nb(c))+" ").indexOf(b)>-1)return!0;return!1}});var ob=/\r/g;r.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=r.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,r(this).val()):a,null==e?e="":"number"==typeof e?e+="":r.isArray(e)&&(e=r.map(e,function(a){return null==a?"":a+""})),b=r.valHooks[this.type]||r.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=r.valHooks[e.type]||r.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(ob,""):null==c?"":c)}}}),r.extend({valHooks:{option:{get:function(a){var b=r.find.attr(a,"value");return null!=b?b:mb(r.text(a))}},select:{get:function(a){var b,c,d,e=a.options,f=a.selectedIndex,g="select-one"===a.type,h=g?null:[],i=g?f+1:e.length;for(d=f<0?i:g?f:0;d-1)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),r.each(["radio","checkbox"],function(){r.valHooks[this]={set:function(a,b){if(r.isArray(b))return a.checked=r.inArray(r(a).val(),b)>-1}},o.checkOn||(r.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var pb=/^(?:focusinfocus|focusoutblur)$/;r.extend(r.event,{trigger:function(b,c,e,f){var g,h,i,j,k,m,n,o=[e||d],p=l.call(b,"type")?b.type:b,q=l.call(b,"namespace")?b.namespace.split("."):[];if(h=i=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!pb.test(p+r.event.triggered)&&(p.indexOf(".")>-1&&(q=p.split("."),p=q.shift(),q.sort()),k=p.indexOf(":")<0&&"on"+p,b=b[r.expando]?b:new r.Event(p,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=q.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:r.makeArray(c,[b]),n=r.event.special[p]||{},f||!n.trigger||n.trigger.apply(e,c)!==!1)){if(!f&&!n.noBubble&&!r.isWindow(e)){for(j=n.delegateType||p,pb.test(j+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),i=h;i===(e.ownerDocument||d)&&o.push(i.defaultView||i.parentWindow||a)}g=0;while((h=o[g++])&&!b.isPropagationStopped())b.type=g>1?j:n.bindType||p,m=(V.get(h,"events")||{})[b.type]&&V.get(h,"handle"),m&&m.apply(h,c),m=k&&h[k],m&&m.apply&&T(h)&&(b.result=m.apply(h,c),b.result===!1&&b.preventDefault());return b.type=p,f||b.isDefaultPrevented()||n._default&&n._default.apply(o.pop(),c)!==!1||!T(e)||k&&r.isFunction(e[p])&&!r.isWindow(e)&&(i=e[k],i&&(e[k]=null),r.event.triggered=p,e[p](),r.event.triggered=void 0,i&&(e[k]=i)),b.result}},simulate:function(a,b,c){var d=r.extend(new r.Event,c,{type:a,isSimulated:!0});r.event.trigger(d,null,b)}}),r.fn.extend({trigger:function(a,b){return this.each(function(){r.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];if(c)return r.event.trigger(a,b,c,!0)}}),r.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(a,b){r.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),r.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),o.focusin="onfocusin"in a,o.focusin||r.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){r.event.simulate(b,a.target,r.event.fix(a))};r.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=V.access(d,b);e||d.addEventListener(a,c,!0),V.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=V.access(d,b)-1;e?V.access(d,b,e):(d.removeEventListener(a,c,!0),V.remove(d,b))}}});var qb=a.location,rb=r.now(),sb=/\?/;r.parseXML=function(b){var c;if(!b||"string"!=typeof b)return null;try{c=(new a.DOMParser).parseFromString(b,"text/xml")}catch(d){c=void 0}return c&&!c.getElementsByTagName("parsererror").length||r.error("Invalid XML: "+b),c};var tb=/\[\]$/,ub=/\r?\n/g,vb=/^(?:submit|button|image|reset|file)$/i,wb=/^(?:input|select|textarea|keygen)/i;function xb(a,b,c,d){var e;if(r.isArray(b))r.each(b,function(b,e){c||tb.test(a)?d(a,e):xb(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d)});else if(c||"object"!==r.type(b))d(a,b);else for(e in b)xb(a+"["+e+"]",b[e],c,d)}r.param=function(a,b){var c,d=[],e=function(a,b){var c=r.isFunction(b)?b():b;d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(null==c?"":c)};if(r.isArray(a)||a.jquery&&!r.isPlainObject(a))r.each(a,function(){e(this.name,this.value)});else for(c in a)xb(c,a[c],b,e);return d.join("&")},r.fn.extend({serialize:function(){return r.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=r.prop(this,"elements");return a?r.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!r(this).is(":disabled")&&wb.test(this.nodeName)&&!vb.test(a)&&(this.checked||!ia.test(a))}).map(function(a,b){var c=r(this).val();return null==c?null:r.isArray(c)?r.map(c,function(a){return{name:b.name,value:a.replace(ub,"\r\n")}}):{name:b.name,value:c.replace(ub,"\r\n")}}).get()}});var yb=/%20/g,zb=/#.*$/,Ab=/([?&])_=[^&]*/,Bb=/^(.*?):[ \t]*([^\r\n]*)$/gm,Cb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Db=/^(?:GET|HEAD)$/,Eb=/^\/\//,Fb={},Gb={},Hb="*/".concat("*"),Ib=d.createElement("a");Ib.href=qb.href;function Jb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(K)||[];if(r.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Kb(a,b,c,d){var e={},f=a===Gb;function g(h){var i;return e[h]=!0,r.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Lb(a,b){var c,d,e=r.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&r.extend(!0,a,d),a}function Mb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}if(f)return f!==i[0]&&i.unshift(f),c[f]}function Nb(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}r.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:qb.href,type:"GET",isLocal:Cb.test(qb.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Hb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":r.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Lb(Lb(a,r.ajaxSettings),b):Lb(r.ajaxSettings,a)},ajaxPrefilter:Jb(Fb),ajaxTransport:Jb(Gb),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var e,f,g,h,i,j,k,l,m,n,o=r.ajaxSetup({},c),p=o.context||o,q=o.context&&(p.nodeType||p.jquery)?r(p):r.event,s=r.Deferred(),t=r.Callbacks("once memory"),u=o.statusCode||{},v={},w={},x="canceled",y={readyState:0,getResponseHeader:function(a){var b;if(k){if(!h){h={};while(b=Bb.exec(g))h[b[1].toLowerCase()]=b[2]}b=h[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return k?g:null},setRequestHeader:function(a,b){return null==k&&(a=w[a.toLowerCase()]=w[a.toLowerCase()]||a,v[a]=b),this},overrideMimeType:function(a){return null==k&&(o.mimeType=a),this},statusCode:function(a){var b;if(a)if(k)y.always(a[y.status]);else for(b in a)u[b]=[u[b],a[b]];return this},abort:function(a){var b=a||x;return e&&e.abort(b),A(0,b),this}};if(s.promise(y),o.url=((b||o.url||qb.href)+"").replace(Eb,qb.protocol+"//"),o.type=c.method||c.type||o.method||o.type,o.dataTypes=(o.dataType||"*").toLowerCase().match(K)||[""],null==o.crossDomain){j=d.createElement("a");try{j.href=o.url,j.href=j.href,o.crossDomain=Ib.protocol+"//"+Ib.host!=j.protocol+"//"+j.host}catch(z){o.crossDomain=!0}}if(o.data&&o.processData&&"string"!=typeof o.data&&(o.data=r.param(o.data,o.traditional)),Kb(Fb,o,c,y),k)return y;l=r.event&&o.global,l&&0===r.active++&&r.event.trigger("ajaxStart"),o.type=o.type.toUpperCase(),o.hasContent=!Db.test(o.type),f=o.url.replace(zb,""),o.hasContent?o.data&&o.processData&&0===(o.contentType||"").indexOf("application/x-www-form-urlencoded")&&(o.data=o.data.replace(yb,"+")):(n=o.url.slice(f.length),o.data&&(f+=(sb.test(f)?"&":"?")+o.data,delete o.data),o.cache===!1&&(f=f.replace(Ab,"$1"),n=(sb.test(f)?"&":"?")+"_="+rb++ +n),o.url=f+n),o.ifModified&&(r.lastModified[f]&&y.setRequestHeader("If-Modified-Since",r.lastModified[f]),r.etag[f]&&y.setRequestHeader("If-None-Match",r.etag[f])),(o.data&&o.hasContent&&o.contentType!==!1||c.contentType)&&y.setRequestHeader("Content-Type",o.contentType),y.setRequestHeader("Accept",o.dataTypes[0]&&o.accepts[o.dataTypes[0]]?o.accepts[o.dataTypes[0]]+("*"!==o.dataTypes[0]?", "+Hb+"; q=0.01":""):o.accepts["*"]);for(m in o.headers)y.setRequestHeader(m,o.headers[m]);if(o.beforeSend&&(o.beforeSend.call(p,y,o)===!1||k))return y.abort();if(x="abort",t.add(o.complete),y.done(o.success),y.fail(o.error),e=Kb(Gb,o,c,y)){if(y.readyState=1,l&&q.trigger("ajaxSend",[y,o]),k)return y;o.async&&o.timeout>0&&(i=a.setTimeout(function(){y.abort("timeout")},o.timeout));try{k=!1,e.send(v,A)}catch(z){if(k)throw z;A(-1,z)}}else A(-1,"No Transport");function A(b,c,d,h){var j,m,n,v,w,x=c;k||(k=!0,i&&a.clearTimeout(i),e=void 0,g=h||"",y.readyState=b>0?4:0,j=b>=200&&b<300||304===b,d&&(v=Mb(o,y,d)),v=Nb(o,v,y,j),j?(o.ifModified&&(w=y.getResponseHeader("Last-Modified"),w&&(r.lastModified[f]=w),w=y.getResponseHeader("etag"),w&&(r.etag[f]=w)),204===b||"HEAD"===o.type?x="nocontent":304===b?x="notmodified":(x=v.state,m=v.data,n=v.error,j=!n)):(n=x,!b&&x||(x="error",b<0&&(b=0))),y.status=b,y.statusText=(c||x)+"",j?s.resolveWith(p,[m,x,y]):s.rejectWith(p,[y,x,n]),y.statusCode(u),u=void 0,l&&q.trigger(j?"ajaxSuccess":"ajaxError",[y,o,j?m:n]),t.fireWith(p,[y,x]),l&&(q.trigger("ajaxComplete",[y,o]),--r.active||r.event.trigger("ajaxStop")))}return y},getJSON:function(a,b,c){return r.get(a,b,c,"json")},getScript:function(a,b){return r.get(a,void 0,b,"script")}}),r.each(["get","post"],function(a,b){r[b]=function(a,c,d,e){return r.isFunction(c)&&(e=e||d,d=c,c=void 0),r.ajax(r.extend({url:a,type:b,dataType:e,data:c,success:d},r.isPlainObject(a)&&a))}}),r._evalUrl=function(a){return r.ajax({url:a,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},r.fn.extend({wrapAll:function(a){var b;return this[0]&&(r.isFunction(a)&&(a=a.call(this[0])),b=r(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this},wrapInner:function(a){return r.isFunction(a)?this.each(function(b){r(this).wrapInner(a.call(this,b))}):this.each(function(){var b=r(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=r.isFunction(a);return this.each(function(c){r(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(a){return this.parent(a).not("body").each(function(){r(this).replaceWith(this.childNodes)}),this}}),r.expr.pseudos.hidden=function(a){return!r.expr.pseudos.visible(a)},r.expr.pseudos.visible=function(a){return!!(a.offsetWidth||a.offsetHeight||a.getClientRects().length)},r.ajaxSettings.xhr=function(){try{return new a.XMLHttpRequest}catch(b){}};var Ob={0:200,1223:204},Pb=r.ajaxSettings.xhr();o.cors=!!Pb&&"withCredentials"in Pb,o.ajax=Pb=!!Pb,r.ajaxTransport(function(b){var c,d;if(o.cors||Pb&&!b.crossDomain)return{send:function(e,f){var g,h=b.xhr();if(h.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(g in b.xhrFields)h[g]=b.xhrFields[g];b.mimeType&&h.overrideMimeType&&h.overrideMimeType(b.mimeType),b.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest");for(g in e)h.setRequestHeader(g,e[g]);c=function(a){return function(){c&&(c=d=h.onload=h.onerror=h.onabort=h.onreadystatechange=null,"abort"===a?h.abort():"error"===a?"number"!=typeof h.status?f(0,"error"):f(h.status,h.statusText):f(Ob[h.status]||h.status,h.statusText,"text"!==(h.responseType||"text")||"string"!=typeof h.responseText?{binary:h.response}:{text:h.responseText},h.getAllResponseHeaders()))}},h.onload=c(),d=h.onerror=c("error"),void 0!==h.onabort?h.onabort=d:h.onreadystatechange=function(){4===h.readyState&&a.setTimeout(function(){c&&d()})},c=c("abort");try{h.send(b.hasContent&&b.data||null)}catch(i){if(c)throw i}},abort:function(){c&&c()}}}),r.ajaxPrefilter(function(a){a.crossDomain&&(a.contents.script=!1)}),r.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(a){return r.globalEval(a),a}}}),r.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),r.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(e,f){b=r(" + + + + + + + + + + + +
      +

      + + + + +
      + + + +
      + +
      + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/jsdoc/hifi-jsdoc-template/tmpl/mainpage.tmpl b/tools/jsdoc/hifi-jsdoc-template/tmpl/mainpage.tmpl new file mode 100644 index 0000000000..b38a185c0f --- /dev/null +++ b/tools/jsdoc/hifi-jsdoc-template/tmpl/mainpage.tmpl @@ -0,0 +1,10 @@ + + + +
      +
      +
      + diff --git a/tools/jsdoc/hifi-jsdoc-template/tmpl/members.tmpl b/tools/jsdoc/hifi-jsdoc-template/tmpl/members.tmpl new file mode 100644 index 0000000000..eef64c1f3f --- /dev/null +++ b/tools/jsdoc/hifi-jsdoc-template/tmpl/members.tmpl @@ -0,0 +1,41 @@ + + + + + + + + + + + + + +
      +
      + Type: +
      + +

      + +

       

      + + + + +
      Example 1? 's':'' ?>
      + + + +
      + + +
      Fires:
      +
        +
      • +
      + + diff --git a/tools/jsdoc/hifi-jsdoc-template/tmpl/method.tmpl b/tools/jsdoc/hifi-jsdoc-template/tmpl/method.tmpl new file mode 100644 index 0000000000..153459f475 --- /dev/null +++ b/tools/jsdoc/hifi-jsdoc-template/tmpl/method.tmpl @@ -0,0 +1,119 @@ + + + + + + + + + + + + + +
      + +
      + Returns: + + + +
      + +

      + + +

      + +

       

      + + + +

      Throws:

      + 1) { ?>
        +
      • +
      +

      + + + + + +

      Parameters

      + + + +
      Example 1? 's':'' ?>
      + + + +
      + + + +
      Extends:
      + + + + +
      Type:
      +
        +
      • + +
      • +
      + + + +
      This:
      +
      + + + +
      Requires:
      +
        +
      • +
      + + + +
      Fires:
      +
        +
      • +
      + + + +
      Listens to Events:
      +
        +
      • +
      + + + +
      Listeners of This Event:
      +
        +
      • +
      + + + +
      Yields:
      + 1) { ?>
        +
      • +
      + + + diff --git a/tools/jsdoc/hifi-jsdoc-template/tmpl/methodList.tmpl b/tools/jsdoc/hifi-jsdoc-template/tmpl/methodList.tmpl new file mode 100644 index 0000000000..7d88cd5e51 --- /dev/null +++ b/tools/jsdoc/hifi-jsdoc-template/tmpl/methodList.tmpl @@ -0,0 +1,107 @@ + + + +

      Constructor

      + + + + + + + + + + None + + 1) { ?>
        +
      • +
      + + + + + + + + + + + + + + + + + +
      Extends:
      + + + + +
      Type:
      +
        +
      • + +
      • +
      + + + +
      This:
      +
      + + + + +
      Requires:
      +
        +
      • +
      + + + +
      Fires:
      +
        +
      • +
      + + + +
      Listens to Events:
      +
        +
      • +
      + + + +
      Listeners of This Event:
      +
        +
      • +
      + + + +
      Yields:
      + 1) { ?>
        +
      • +
      + + + + \ No newline at end of file diff --git a/tools/jsdoc/hifi-jsdoc-template/tmpl/paramList.tmpl b/tools/jsdoc/hifi-jsdoc-template/tmpl/paramList.tmpl new file mode 100644 index 0000000000..5b5164b771 --- /dev/null +++ b/tools/jsdoc/hifi-jsdoc-template/tmpl/paramList.tmpl @@ -0,0 +1,67 @@ + + + + + + + , + + + diff --git a/tools/jsdoc/hifi-jsdoc-template/tmpl/params.tmpl b/tools/jsdoc/hifi-jsdoc-template/tmpl/params.tmpl new file mode 100644 index 0000000000..17f58b1677 --- /dev/null +++ b/tools/jsdoc/hifi-jsdoc-template/tmpl/params.tmpl @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      NameTypeAttributesDefaultDescription
      + + + + + + Default Value: + + +
      Properties
      + +
      \ No newline at end of file diff --git a/tools/jsdoc/hifi-jsdoc-template/tmpl/properties.tmpl b/tools/jsdoc/hifi-jsdoc-template/tmpl/properties.tmpl new file mode 100644 index 0000000000..5c83a7d587 --- /dev/null +++ b/tools/jsdoc/hifi-jsdoc-template/tmpl/properties.tmpl @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      NameTypeAttributesSummary
      + + + + + + <optional>
      + + + + <nullable>
      + +
      + + + +

      Default Value:

      + + + +
      Properties
      + +
      diff --git a/tools/jsdoc/hifi-jsdoc-template/tmpl/returns.tmpl b/tools/jsdoc/hifi-jsdoc-template/tmpl/returns.tmpl new file mode 100644 index 0000000000..3958e7018e --- /dev/null +++ b/tools/jsdoc/hifi-jsdoc-template/tmpl/returns.tmpl @@ -0,0 +1,8 @@ + + + + + diff --git a/tools/jsdoc/hifi-jsdoc-template/tmpl/returnsSimp.tmpl b/tools/jsdoc/hifi-jsdoc-template/tmpl/returnsSimp.tmpl new file mode 100644 index 0000000000..b93aa50ad4 --- /dev/null +++ b/tools/jsdoc/hifi-jsdoc-template/tmpl/returnsSimp.tmpl @@ -0,0 +1,6 @@ + + + + + diff --git a/tools/jsdoc/hifi-jsdoc-template/tmpl/signal.tmpl b/tools/jsdoc/hifi-jsdoc-template/tmpl/signal.tmpl new file mode 100644 index 0000000000..20743fe052 --- /dev/null +++ b/tools/jsdoc/hifi-jsdoc-template/tmpl/signal.tmpl @@ -0,0 +1,123 @@ + + + + + + + + + + + + + +
      + ( + + + + ) +
      + Returns: + + + +
      + +

      + + +

      + +

       

      + + + +

      Throws:

      + 1) { ?>
        +
      • +
      +

      + + + + + +

      Parameters

      + + + +
      Example 1? 's':'' ?>
      + + + +
      + + + +
      Extends:
      + + + + +
      Type:
      +
        +
      • + +
      • +
      + + + +
      This:
      +
      + + + +
      Requires:
      +
        +
      • +
      + + + +
      Fires:
      +
        +
      • +
      + + + +
      Listens to Events:
      +
        +
      • +
      + + + +
      Listeners of This Event:
      +
        +
      • +
      + + + +
      Yields:
      + 1) { ?>
        +
      • +
      + + + diff --git a/tools/jsdoc/hifi-jsdoc-template/tmpl/signalList.tmpl b/tools/jsdoc/hifi-jsdoc-template/tmpl/signalList.tmpl new file mode 100644 index 0000000000..b9a0e0ca86 --- /dev/null +++ b/tools/jsdoc/hifi-jsdoc-template/tmpl/signalList.tmpl @@ -0,0 +1,92 @@ + + + +

      Constructor

      + + + + + + + + + + + + + + + + + + + + +
      Extends:
      + + + + +
      Type:
      +
        +
      • + +
      • +
      + + + +
      This:
      +
      + + + + +
      Requires:
      +
        +
      • +
      + + + +
      Fires:
      +
        +
      • +
      + + + +
      Listens to Events:
      +
        +
      • +
      + + + +
      Listeners of This Event:
      +
        +
      • +
      + + + +
      Yields:
      + 1) { ?>
        +
      • +
      + + + + \ No newline at end of file diff --git a/tools/jsdoc/hifi-jsdoc-template/tmpl/source.tmpl b/tools/jsdoc/hifi-jsdoc-template/tmpl/source.tmpl new file mode 100644 index 0000000000..e559b5d103 --- /dev/null +++ b/tools/jsdoc/hifi-jsdoc-template/tmpl/source.tmpl @@ -0,0 +1,8 @@ + +
      +
      +
      +
      +
      \ No newline at end of file diff --git a/tools/jsdoc/hifi-jsdoc-template/tmpl/tutorial.tmpl b/tools/jsdoc/hifi-jsdoc-template/tmpl/tutorial.tmpl new file mode 100644 index 0000000000..88a0ad52aa --- /dev/null +++ b/tools/jsdoc/hifi-jsdoc-template/tmpl/tutorial.tmpl @@ -0,0 +1,19 @@ +
      + +
      + 0) { ?> +
        +
      • +
      + + +

      +
      + +
      + +
      + +
      diff --git a/tools/jsdoc/hifi-jsdoc-template/tmpl/type.tmpl b/tools/jsdoc/hifi-jsdoc-template/tmpl/type.tmpl new file mode 100644 index 0000000000..8f8d89369d --- /dev/null +++ b/tools/jsdoc/hifi-jsdoc-template/tmpl/type.tmpl @@ -0,0 +1,7 @@ + + +| + \ No newline at end of file diff --git a/tools/jsdoc/plugins/hifi.js b/tools/jsdoc/plugins/hifi.js index a525093965..b61c80284c 100644 --- a/tools/jsdoc/plugins/hifi.js +++ b/tools/jsdoc/plugins/hifi.js @@ -107,9 +107,6 @@ exports.handlers = { if (e.doclet.hifiClientEntity) { rows.push("Client Entity Scripts"); } - if (e.doclet.hifiAvatar) { - rows.push("Avatar Scripts"); - } if (e.doclet.hifiServerEntity) { rows.push("Server Entity Scripts"); } @@ -117,15 +114,31 @@ exports.handlers = { rows.push("Assignment Client Scripts"); } - // Append an Available In: table at the end of the namespace description. + // Append an Available In: sentence at the beginning of the namespace description. if (rows.length > 0) { - var table = "
      Available in:" + rows.join("") + "

      "; - e.doclet.description = table + (e.doclet.description ? e.doclet.description : ""); - } + var availableIn = "

      Supported Script Types: " + rows.join(" • ") + "

      "; + + e.doclet.description = (e.doclet.description ? e.doclet.description : "") + availableIn; + } } } }; +// Functions for adding @signal custom tag +/** @private */ +function setDocletKindToTitle(doclet, tag) { + doclet.addTag( 'kind', tag.title ); +} + +function setDocletNameToValue(doclet, tag) { + if (tag.value && tag.value.description) { // as in a long tag + doclet.addTag('name', tag.value.description); + } + else if (tag.text) { // or a short tag + doclet.addTag('name', tag.text); + } +} + // Define custom hifi tags here exports.defineTags = function (dictionary) { @@ -143,14 +156,6 @@ exports.defineTags = function (dictionary) { } }); - // @hifi-avatar-script - dictionary.defineTag("hifi-avatar", { - onTagged: function (doclet, tag) { - doclet.hifiAvatar = true; - } - }); - - // @hifi-client-entity dictionary.defineTag("hifi-client-entity", { onTagged: function (doclet, tag) { From 75000d9a798dea718fd001ba727896a30fb41916 Mon Sep 17 00:00:00 2001 From: ingerjm0 Date: Sat, 23 Feb 2019 21:28:00 -0800 Subject: [PATCH 08/44] Add @signal tag to hifi plugin --- tools/jsdoc/plugins/hifi.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tools/jsdoc/plugins/hifi.js b/tools/jsdoc/plugins/hifi.js index b61c80284c..16969b18fe 100644 --- a/tools/jsdoc/plugins/hifi.js +++ b/tools/jsdoc/plugins/hifi.js @@ -169,4 +169,14 @@ exports.defineTags = function (dictionary) { doclet.hifiServerEntity = true; } }); + + // @signal + dictionary.defineTag("signal", { + mustHaveValue: true, + onTagged: function(doclet, tag) { + setDocletKindToTitle(doclet, tag); + setDocletNameToValue(doclet, tag); + } + }); + }; \ No newline at end of file From 761a9229511efce10c68a77f00805b8220af0a05 Mon Sep 17 00:00:00 2001 From: ingerjm0 Date: Mon, 25 Feb 2019 10:43:14 -0800 Subject: [PATCH 09/44] Fixed per code review --- tools/jsdoc/plugins/hifi.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/jsdoc/plugins/hifi.js b/tools/jsdoc/plugins/hifi.js index 16969b18fe..b4350ddbdb 100644 --- a/tools/jsdoc/plugins/hifi.js +++ b/tools/jsdoc/plugins/hifi.js @@ -133,8 +133,7 @@ function setDocletKindToTitle(doclet, tag) { function setDocletNameToValue(doclet, tag) { if (tag.value && tag.value.description) { // as in a long tag doclet.addTag('name', tag.value.description); - } - else if (tag.text) { // or a short tag + } else if (tag.text) { // or a short tag doclet.addTag('name', tag.text); } } From 8dadeb197bc4ef84858aef1cea6eb4b605e13b75 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Fri, 1 Mar 2019 11:35:08 -0800 Subject: [PATCH 10/44] Corrected error message. --- tools/nitpick/src/AdbInterface.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tools/nitpick/src/AdbInterface.cpp b/tools/nitpick/src/AdbInterface.cpp index 82ef1446e3..41eb947efa 100644 --- a/tools/nitpick/src/AdbInterface.cpp +++ b/tools/nitpick/src/AdbInterface.cpp @@ -16,12 +16,13 @@ QString AdbInterface::getAdbCommand() { #ifdef Q_OS_WIN if (_adbCommand.isNull()) { - QString adbPath = PathUtils::getPathToExecutable("adb.exe"); + QString adbExe{ "adb.exe" }; + QString adbPath = PathUtils::getPathToExecutable(adbExe); if (!adbPath.isNull()) { - _adbCommand = adbPath + _adbExe; + _adbCommand = adbExe; } else { - QMessageBox::critical(0, "python.exe not found", - "Please verify that pyton.exe is in the PATH"); + QMessageBox::critical(0, "adb.exe not found", + "Please verify that adb.exe is in the PATH"); exit(-1); } } From 6697d9d49f097aa7b582f2bd22a7e437252b106c Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Fri, 1 Mar 2019 12:32:55 -0800 Subject: [PATCH 11/44] Use python downloader. --- tools/nitpick/README.md | 14 +- tools/nitpick/src/AWSInterface.cpp | 2 +- tools/nitpick/src/AdbInterface.h | 6 - tools/nitpick/src/Downloader.cpp | 71 +- tools/nitpick/src/Downloader.h | 29 +- tools/nitpick/src/Nitpick.cpp | 139 +-- tools/nitpick/src/Nitpick.h | 31 +- tools/nitpick/src/Test.cpp | 1116 ----------------------- tools/nitpick/src/Test.h | 168 ---- tools/nitpick/src/TestRailInterface.cpp | 4 +- tools/nitpick/src/TestRunner.cpp | 22 +- tools/nitpick/src/TestRunner.h | 20 +- tools/nitpick/src/TestRunnerDesktop.cpp | 51 +- tools/nitpick/src/TestRunnerDesktop.h | 5 +- tools/nitpick/src/TestRunnerMobile.cpp | 62 +- tools/nitpick/src/TestRunnerMobile.h | 4 +- tools/nitpick/ui/Nitpick.ui | 185 +++- 17 files changed, 424 insertions(+), 1505 deletions(-) delete mode 100644 tools/nitpick/src/Test.cpp delete mode 100644 tools/nitpick/src/Test.h diff --git a/tools/nitpick/README.md b/tools/nitpick/README.md index c7b9050070..62e614c214 100644 --- a/tools/nitpick/README.md +++ b/tools/nitpick/README.md @@ -47,14 +47,20 @@ These steps assume the hifi repository has been cloned to `~/hifi`. ### Windows 1. (First time) download and install Python 3 from https://hifi-qa.s3.amazonaws.com/nitpick/Windows/python-3.7.0-amd64.exe (also located at https://www.python.org/downloads/) 1. Click the "add python to path" checkbox on the python installer - 1. After installation - add the path to python.exe to the Windows PATH environment variable. + 1. After installation: + 1. Open a new terminal + 1. Enter `python` and hit enter + 1. Verify that python is available (the prompt will change to `>>>`) + 1. Type `exit()` and hit enter to close python + 1. Install requests (a python library to download files from URLs) + `pip3 install requests` 1. (First time) download and install AWS CLI from https://hifi-qa.s3.amazonaws.com/nitpick/Windows/AWSCLI64PY3.msi (also available at https://aws.amazon.com/cli/ 1. Open a new command prompt and run `aws configure` 1. Enter the AWS account number 1. Enter the secret key 1. Leave region name and ouput format as default [None] - 1. Install the latest release of Boto3 via pip: + 1. Install the latest release of Boto3 via pip (from a terminal): `pip install boto3` 1. (First time) Download adb (Android Debug Bridge) from *https://dl.google.com/android/repository/platform-tools-latest-windows.zip* @@ -76,11 +82,13 @@ These steps assume the hifi repository has been cloned to `~/hifi`. `open "/Applications/Python 3.7/Install Certificates.command"`. This is needed because the Mac Python supplied no longer links with the deprecated Apple-supplied system OpenSSL libraries but rather supplies a private copy of OpenSSL 1.0.2 which does not automatically access the system default root certificates. 1. Verify that `/usr/local/bin/python3` exists. -1. (First time - AWS interface) Install pip with the script provided by the Python Packaging Authority: In a terminal: `curl -O https://bootstrap.pypa.io/get-pip.py` In a terminal: `python3 get-pip.py --user` + 1. Install requests (a python library to download files from URLs) + `pip3 install requests` +1. (First time - AWS interface) Install pip with the script provided by the Python Packaging Authority: 1. Use pip to install the AWS CLI. `pip3 install awscli --upgrade --user` This will install aws in your user. For user XXX, aws will be located in ~/Library/Python/3.7/bin diff --git a/tools/nitpick/src/AWSInterface.cpp b/tools/nitpick/src/AWSInterface.cpp index 4e83460b9e..7e11bd80fc 100644 --- a/tools/nitpick/src/AWSInterface.cpp +++ b/tools/nitpick/src/AWSInterface.cpp @@ -469,7 +469,7 @@ void AWSInterface::updateAWS() { if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), - "Could not create 'addTestCases.py'"); + "Could not create 'updateAWS.py'"); exit(-1); } diff --git a/tools/nitpick/src/AdbInterface.h b/tools/nitpick/src/AdbInterface.h index c1ce84c019..a2aa2be8ea 100644 --- a/tools/nitpick/src/AdbInterface.h +++ b/tools/nitpick/src/AdbInterface.h @@ -17,12 +17,6 @@ public: QString getAdbCommand(); private: -#ifdef Q_OS_WIN - const QString _adbExe{ "adb.exe" }; -#else - // Both Mac and Linux use "python" - const QString _adbExe{ "adb" }; -#endif QString _adbCommand; }; diff --git a/tools/nitpick/src/Downloader.cpp b/tools/nitpick/src/Downloader.cpp index 3256e79601..26e2140dbd 100644 --- a/tools/nitpick/src/Downloader.cpp +++ b/tools/nitpick/src/Downloader.cpp @@ -8,32 +8,65 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include "Downloader.h" +#include "PythonInterface.h" -#include +#include +#include +#include +#include +#include -Downloader::Downloader(QUrl fileURL, QObject *parent) : QObject(parent) { - _networkAccessManager.get(QNetworkRequest(fileURL)); - - connect( - &_networkAccessManager, SIGNAL (finished(QNetworkReply*)), - this, SLOT (fileDownloaded(QNetworkReply*)) - ); +Downloader::Downloader() { + PythonInterface* pythonInterface = new PythonInterface(); + _pythonCommand = pythonInterface->getPythonCommand(); } -void Downloader::fileDownloaded(QNetworkReply* reply) { - QNetworkReply::NetworkError error = reply->error(); - if (error != QNetworkReply::NetworkError::NoError) { - QMessageBox::information(0, "Test Aborted", "Failed to download file: " + reply->errorString()); +void Downloader::downloadFiles(const QStringList& URLs, const QString& directoryName, const QStringList& filenames, void *caller) { + if (URLs.size() <= 0) { return; } - _downloadedData = reply->readAll(); + QString filename = directoryName + "/downloadFiles.py"; + if (QFile::exists(filename)) { + QFile::remove(filename); + } + QFile file(filename); - //emit a signal - reply->deleteLater(); - emit downloaded(); -} + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), + "Could not create 'downloadFiles.py'"); + exit(-1); + } -QByteArray Downloader::downloadedData() const { - return _downloadedData; + QTextStream stream(&file); + + stream << "import requests\n"; + + for (int i = 0; i < URLs.size(); ++i) { + stream << "\nurl = '" + URLs[i] + "'\n"; + stream << "r = requests.get(url)\n"; + stream << "open('" + directoryName + '/' + filenames [i] + "', 'wb').write(r.content)\n"; + } + + file.close(); + +#ifdef Q_OS_WIN + QProcess* process = new QProcess(); + connect(process, &QProcess::started, this, [=]() { _busyWindow.exec(); }); + connect(process, SIGNAL(finished(int)), process, SLOT(deleteLater())); + connect(process, static_cast(&QProcess::finished), this, + [=](int exitCode, QProcess::ExitStatus exitStatus) { _busyWindow.hide(); }); + + QStringList parameters = QStringList() << filename; + process->start(_pythonCommand, parameters); +#elif defined Q_OS_MAC + QProcess* process = new QProcess(); + QStringList parameters = QStringList() << "-c" << _pythonCommand + " " + filename; + process->start("sh", parameters); + + // Wait for the last file to download + while (!QFile::exists(directoryName + '/' + filenames[filenames.length() - 1])) { + QThread::msleep(200); + } +#endif } diff --git a/tools/nitpick/src/Downloader.h b/tools/nitpick/src/Downloader.h index 742a88b890..e48c195999 100644 --- a/tools/nitpick/src/Downloader.h +++ b/tools/nitpick/src/Downloader.h @@ -11,38 +11,19 @@ #ifndef hifi_downloader_h #define hifi_downloader_h -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "BusyWindow.h" #include -#include -#include -#include -#include - class Downloader : public QObject { Q_OBJECT public: - explicit Downloader(QUrl fileURL, QObject *parent = 0); + Downloader(); - QByteArray downloadedData() const; - -signals: - void downloaded(); - -private slots: - void fileDownloaded(QNetworkReply* pReply); + void downloadFiles(const QStringList& URLs, const QString& directoryName, const QStringList& filenames, void *caller); private: - QNetworkAccessManager _networkAccessManager; - QByteArray _downloadedData; + QString _pythonCommand; + BusyWindow _busyWindow; }; #endif // hifi_downloader_h \ No newline at end of file diff --git a/tools/nitpick/src/Nitpick.cpp b/tools/nitpick/src/Nitpick.cpp index 39800c6bc6..03acd4a893 100644 --- a/tools/nitpick/src/Nitpick.cpp +++ b/tools/nitpick/src/Nitpick.cpp @@ -24,8 +24,6 @@ Nitpick::Nitpick(QWidget* parent) : QMainWindow(parent) { _ui.progressBar->setVisible(false); _ui.tabWidget->setCurrentIndex(0); - _signalMapper = new QSignalMapper(); - connect(_ui.actionClose, &QAction::triggered, this, &Nitpick::on_closePushbutton_clicked); connect(_ui.actionAbout, &QAction::triggered, this, &Nitpick::about); connect(_ui.actionContent, &QAction::triggered, this, &Nitpick::content); @@ -40,7 +38,7 @@ Nitpick::Nitpick(QWidget* parent) : QMainWindow(parent) { _ui.plainTextEdit->setReadOnly(true); - setWindowTitle("Nitpick - v3.0.0"); + setWindowTitle("Nitpick - v3.1.0"); clientProfiles << "VR-High" << "Desktop-High" << "Desktop-Low" << "Mobile-Touch" << "VR-Standalone"; _ui.clientProfileComboBox->insertItems(0, clientProfiles); @@ -48,10 +46,8 @@ Nitpick::Nitpick(QWidget* parent) : QMainWindow(parent) { } Nitpick::~Nitpick() { - delete _signalMapper; - - if (_test) { - delete _test; + if (_testCreator) { + delete _testCreator; } if (_testRunnerDesktop) { @@ -64,10 +60,10 @@ Nitpick::~Nitpick() { } void Nitpick::setup() { - if (_test) { - delete _test; + if (_testCreator) { + delete _testCreator; } - _test = new Test(_ui.progressBar, _ui.checkBoxInteractiveMode); + _testCreator = new TestCreator(_ui.progressBar, _ui.checkBoxInteractiveMode); std::vector dayCheckboxes; dayCheckboxes.emplace_back(_ui.mondayCheckBox); @@ -99,9 +95,12 @@ void Nitpick::setup() { timeEditCheckboxes, timeEdits, _ui.workingFolderRunOnDesktopLabel, - _ui.checkBoxServerless, + _ui.checkBoxServerless, + _ui.usePreviousInstallationOnDesktopCheckBox, _ui.runLatestOnDesktopCheckBox, _ui.urlOnDesktopLineEdit, + _ui.runFullSuiteOnDesktopCheckBox, + _ui.scriptURLOnDesktopLineEdit, _ui.runNowPushbutton, _ui.statusLabelOnDesktop ); @@ -118,8 +117,11 @@ void Nitpick::setup() { _ui.downloadAPKPushbutton, _ui.installAPKPushbutton, _ui.runInterfacePushbutton, + _ui.usePreviousInstallationOnMobileCheckBox, _ui.runLatestOnMobileCheckBox, _ui.urlOnMobileLineEdit, + _ui.runFullSuiteOnMobileCheckBox, + _ui.scriptURLOnMobileLineEdit, _ui.statusLabelOnMobile ); } @@ -130,7 +132,7 @@ void Nitpick::startTestsEvaluation(const bool isRunningFromCommandLine, const QString& branch, const QString& user ) { - _test->startTestsEvaluation(isRunningFromCommandLine, isRunningInAutomaticTestRun, snapshotDirectory, branch, user); + _testCreator->startTestsEvaluation(isRunningFromCommandLine, isRunningInAutomaticTestRun, snapshotDirectory, branch, user); } void Nitpick::on_tabWidget_currentChanged(int index) { @@ -149,47 +151,47 @@ void Nitpick::on_tabWidget_currentChanged(int index) { } void Nitpick::on_evaluateTestsPushbutton_clicked() { - _test->startTestsEvaluation(false, false); + _testCreator->startTestsEvaluation(false, false); } void Nitpick::on_createRecursiveScriptPushbutton_clicked() { - _test->createRecursiveScript(); + _testCreator->createRecursiveScript(); } void Nitpick::on_createAllRecursiveScriptsPushbutton_clicked() { - _test->createAllRecursiveScripts(); + _testCreator->createAllRecursiveScripts(); } void Nitpick::on_createTestsPushbutton_clicked() { - _test->createTests(_ui.clientProfileComboBox->currentText()); + _testCreator->createTests(_ui.clientProfileComboBox->currentText()); } void Nitpick::on_createMDFilePushbutton_clicked() { - _test->createMDFile(); + _testCreator->createMDFile(); } void Nitpick::on_createAllMDFilesPushbutton_clicked() { - _test->createAllMDFiles(); + _testCreator->createAllMDFiles(); } void Nitpick::on_createTestAutoScriptPushbutton_clicked() { - _test->createTestAutoScript(); + _testCreator->createTestAutoScript(); } void Nitpick::on_createAllTestAutoScriptsPushbutton_clicked() { - _test->createAllTestAutoScripts(); + _testCreator->createAllTestAutoScripts(); } void Nitpick::on_createTestsOutlinePushbutton_clicked() { - _test->createTestsOutline(); + _testCreator->createTestsOutline(); } void Nitpick::on_createTestRailTestCasesPushbutton_clicked() { - _test->createTestRailTestCases(); + _testCreator->createTestRailTestCases(); } void Nitpick::on_createTestRailRunButton_clicked() { - _test->createTestRailRun(); + _testCreator->createTestRailRun(); } void Nitpick::on_setWorkingFolderRunOnDesktopPushbutton_clicked() { @@ -206,16 +208,25 @@ void Nitpick::on_runNowPushbutton_clicked() { _testRunnerDesktop->run(); } +void Nitpick::on_usePreviousInstallationOnDesktopCheckBox_clicked() { + _ui.runLatestOnDesktopCheckBox->setEnabled(!_ui.usePreviousInstallationOnDesktopCheckBox->isChecked()); + _ui.urlOnDesktopLineEdit->setEnabled(!_ui.usePreviousInstallationOnDesktopCheckBox->isChecked() && !_ui.runLatestOnDesktopCheckBox->isChecked()); +} + void Nitpick::on_runLatestOnDesktopCheckBox_clicked() { _ui.urlOnDesktopLineEdit->setEnabled(!_ui.runLatestOnDesktopCheckBox->isChecked()); } +void Nitpick::on_runFullSuiteOnDesktopCheckBox_clicked() { + _ui.scriptURLOnDesktopLineEdit->setEnabled(!_ui.runFullSuiteOnDesktopCheckBox->isChecked()); +} + void Nitpick::automaticTestRunEvaluationComplete(QString zippedFolderName, int numberOfFailures) { _testRunnerDesktop->automaticTestRunEvaluationComplete(zippedFolderName, numberOfFailures); } void Nitpick::on_updateTestRailRunResultsPushbutton_clicked() { - _test->updateTestRailRunResult(); + _testCreator->updateTestRailRunResult(); } // To toggle between show and hide @@ -247,80 +258,15 @@ void Nitpick::on_closePushbutton_clicked() { } void Nitpick::on_createPythonScriptRadioButton_clicked() { - _test->setTestRailCreateMode(PYTHON); + _testCreator->setTestRailCreateMode(PYTHON); } void Nitpick::on_createXMLScriptRadioButton_clicked() { - _test->setTestRailCreateMode(XML); + _testCreator->setTestRailCreateMode(XML); } void Nitpick::on_createWebPagePushbutton_clicked() { - _test->createWebPage(_ui.updateAWSCheckBox, _ui.awsURLLineEdit); -} - -void Nitpick::downloadFile(const QUrl& url) { - _downloaders.emplace_back(new Downloader(url, this)); - connect(_downloaders[_index], SIGNAL(downloaded()), _signalMapper, SLOT(map())); - - _signalMapper->setMapping(_downloaders[_index], _index); - - ++_index; -} - -void Nitpick::downloadFiles(const QStringList& URLs, const QString& directoryName, const QStringList& filenames, void *caller) { - connect(_signalMapper, SIGNAL(mapped(int)), this, SLOT(saveFile(int))); - - _directoryName = directoryName; - _filenames = filenames; - _caller = caller; - - _numberOfFilesToDownload = URLs.size(); - _numberOfFilesDownloaded = 0; - _index = 0; - - _ui.progressBar->setMinimum(0); - _ui.progressBar->setMaximum(_numberOfFilesToDownload - 1); - _ui.progressBar->setValue(0); - _ui.progressBar->setVisible(true); - - foreach (auto downloader, _downloaders) { - delete downloader; - } - - _downloaders.clear(); - for (int i = 0; i < _numberOfFilesToDownload; ++i) { - downloadFile(URLs[i]); - } -} - -void Nitpick::saveFile(int index) { - try { - QFile file(_directoryName + "/" + _filenames[index]); - file.open(QIODevice::WriteOnly); - file.write(_downloaders[index]->downloadedData()); - file.close(); - } catch (...) { - QMessageBox::information(0, "Test Aborted", "Failed to save file: " + _filenames[index]); - _ui.progressBar->setVisible(false); - return; - } - - ++_numberOfFilesDownloaded; - - if (_numberOfFilesDownloaded == _numberOfFilesToDownload) { - disconnect(_signalMapper, SIGNAL(mapped(int)), this, SLOT(saveFile(int))); - if (_caller == _test) { - _test->finishTestsEvaluation(); - } else if (_caller == _testRunnerDesktop) { - _testRunnerDesktop->downloadComplete(); - } else if (_caller == _testRunnerMobile) { - _testRunnerMobile->downloadComplete(); - } - - _ui.progressBar->setVisible(false); - } else { - _ui.progressBar->setValue(_numberOfFilesDownloaded); - } + _testCreator->createWebPage(_ui.updateAWSCheckBox, _ui.awsURLLineEdit); } void Nitpick::about() { @@ -360,10 +306,19 @@ void Nitpick::on_connectDevicePushbutton_clicked() { _testRunnerMobile->connectDevice(); } +void Nitpick::on_usePreviousInstallationOnMobileCheckBox_clicked() { + _ui.runLatestOnMobileCheckBox->setEnabled(!_ui.usePreviousInstallationOnMobileCheckBox->isChecked()); + _ui.urlOnMobileLineEdit->setEnabled(!_ui.usePreviousInstallationOnMobileCheckBox->isChecked() && !_ui.runLatestOnMobileCheckBox->isChecked()); +} + void Nitpick::on_runLatestOnMobileCheckBox_clicked() { _ui.urlOnMobileLineEdit->setEnabled(!_ui.runLatestOnMobileCheckBox->isChecked()); } +void Nitpick::on_runFullSuiteOnMobileCheckBox_clicked() { + _ui.scriptURLOnMobileLineEdit->setEnabled(!_ui.runFullSuiteOnMobileCheckBox->isChecked()); +} + void Nitpick::on_downloadAPKPushbutton_clicked() { _testRunnerMobile->downloadAPK(); } diff --git a/tools/nitpick/src/Nitpick.h b/tools/nitpick/src/Nitpick.h index 80fef934d6..1e9d7bdee5 100644 --- a/tools/nitpick/src/Nitpick.h +++ b/tools/nitpick/src/Nitpick.h @@ -11,12 +11,10 @@ #define hifi_Nitpick_h #include -#include #include #include "ui_Nitpick.h" -#include "Downloader.h" -#include "Test.h" +#include "TestCreator.h" #include "TestRunnerDesktop.h" #include "TestRunnerMobile.h" @@ -38,9 +36,6 @@ public: void automaticTestRunEvaluationComplete(QString zippedFolderName, int numberOfFailures); - void downloadFile(const QUrl& url); - void downloadFiles(const QStringList& URLs, const QString& directoryName, const QStringList& filenames, void* caller); - void setUserText(const QString& user); QString getSelectedUser(); @@ -75,7 +70,9 @@ private slots: void on_setWorkingFolderRunOnDesktopPushbutton_clicked(); void on_runNowPushbutton_clicked(); + void on_usePreviousInstallationOnDesktopCheckBox_clicked(); void on_runLatestOnDesktopCheckBox_clicked(); + void on_runFullSuiteOnDesktopCheckBox_clicked(); void on_updateTestRailRunResultsPushbutton_clicked(); @@ -87,15 +84,16 @@ private slots: void on_createWebPagePushbutton_clicked(); - void saveFile(int index); - void about(); void content(); // Run on Mobile controls void on_setWorkingFolderRunOnMobilePushbutton_clicked(); void on_connectDevicePushbutton_clicked(); + + void on_usePreviousInstallationOnMobileCheckBox_clicked(); void on_runLatestOnMobileCheckBox_clicked(); + void on_runFullSuiteOnMobileCheckBox_clicked(); void on_downloadAPKPushbutton_clicked(); void on_installAPKPushbutton_clicked(); @@ -105,28 +103,13 @@ private slots: private: Ui::NitpickClass _ui; - Test* _test{ nullptr }; + TestCreator* _testCreator{ nullptr }; TestRunnerDesktop* _testRunnerDesktop{ nullptr }; TestRunnerMobile* _testRunnerMobile{ nullptr }; - std::vector _downloaders; - - // local storage for parameters - folder to store downloaded files in, and a list of their names - QString _directoryName; - QStringList _filenames; - - // Used to enable passing a parameter to slots - QSignalMapper* _signalMapper; - - int _numberOfFilesToDownload{ 0 }; - int _numberOfFilesDownloaded{ 0 }; - int _index{ 0 }; - bool _isRunningFromCommandline{ false }; - void* _caller; - QStringList clientProfiles; }; diff --git a/tools/nitpick/src/Test.cpp b/tools/nitpick/src/Test.cpp deleted file mode 100644 index e8e284bf32..0000000000 --- a/tools/nitpick/src/Test.cpp +++ /dev/null @@ -1,1116 +0,0 @@ -// -// Test.cpp -// -// Created by Nissim Hadar on 2 Nov 2017. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// -#include "Test.h" - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "Nitpick.h" -extern Nitpick* nitpick; - -#include - -Test::Test(QProgressBar* progressBar, QCheckBox* checkBoxInteractiveMode) : _awsInterface(NULL) { - _progressBar = progressBar; - _checkBoxInteractiveMode = checkBoxInteractiveMode; - - _mismatchWindow.setModal(true); - - if (nitpick) { - nitpick->setUserText(GIT_HUB_DEFAULT_USER); - nitpick->setBranchText(GIT_HUB_DEFAULT_BRANCH); - } -} - -bool Test::createTestResultsFolderPath(const QString& directory) { - QDateTime now = QDateTime::currentDateTime(); - _testResultsFolderPath = directory + "/" + TEST_RESULTS_FOLDER + "--" + now.toString(DATETIME_FORMAT) + "(local)[" + QHostInfo::localHostName() + "]"; - QDir testResultsFolder(_testResultsFolderPath); - - // Create a new test results folder - return QDir().mkdir(_testResultsFolderPath); -} - -QString Test::zipAndDeleteTestResultsFolder() { - QString zippedResultsFileName { _testResultsFolderPath + ".zip" }; - QFileInfo fileInfo(zippedResultsFileName); - if (fileInfo.exists()) { - QFile::remove(zippedResultsFileName); - } - - QDir testResultsFolder(_testResultsFolderPath); - JlCompress::compressDir(_testResultsFolderPath + ".zip", _testResultsFolderPath); - - testResultsFolder.removeRecursively(); - - //In all cases, for the next evaluation - _testResultsFolderPath = ""; - _failureIndex = 1; - _successIndex = 1; - - return zippedResultsFileName; -} - -int Test::compareImageLists() { - _progressBar->setMinimum(0); - _progressBar->setMaximum(_expectedImagesFullFilenames.length() - 1); - _progressBar->setValue(0); - _progressBar->setVisible(true); - - // Loop over both lists and compare each pair of images - // Quit loop if user has aborted due to a failed test. - bool keepOn{ true }; - int numberOfFailures{ 0 }; - for (int i = 0; keepOn && i < _expectedImagesFullFilenames.length(); ++i) { - // First check that images are the same size - QImage resultImage(_resultImagesFullFilenames[i]); - QImage expectedImage(_expectedImagesFullFilenames[i]); - - double similarityIndex; // in [-1.0 .. 1.0], where 1.0 means images are identical - - bool isInteractiveMode = (!_isRunningFromCommandLine && _checkBoxInteractiveMode->isChecked() && !_isRunningInAutomaticTestRun); - - // similarityIndex is set to -100.0 to indicate images are not the same size - if (isInteractiveMode && (resultImage.width() != expectedImage.width() || resultImage.height() != expectedImage.height())) { - QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Images are not the same size"); - similarityIndex = -100.0; - } else { - similarityIndex = _imageComparer.compareImages(resultImage, expectedImage); - } - - TestResult testResult = TestResult{ - (float)similarityIndex, - _expectedImagesFullFilenames[i].left(_expectedImagesFullFilenames[i].lastIndexOf("/") + 1), // path to the test (including trailing /) - QFileInfo(_expectedImagesFullFilenames[i].toStdString().c_str()).fileName(), // filename of expected image - QFileInfo(_resultImagesFullFilenames[i].toStdString().c_str()).fileName() // filename of result image - }; - - _mismatchWindow.setTestResult(testResult); - - if (similarityIndex < THRESHOLD) { - ++numberOfFailures; - - if (!isInteractiveMode) { - appendTestResultsToFile(testResult, _mismatchWindow.getComparisonImage(), true); - } else { - _mismatchWindow.exec(); - - switch (_mismatchWindow.getUserResponse()) { - case USER_RESPONSE_PASS: - break; - case USE_RESPONSE_FAIL: - appendTestResultsToFile(testResult, _mismatchWindow.getComparisonImage(), true); - break; - case USER_RESPONSE_ABORT: - keepOn = false; - break; - default: - assert(false); - break; - } - } - } else { - appendTestResultsToFile(testResult, _mismatchWindow.getComparisonImage(), false); - } - - _progressBar->setValue(i); - } - - _progressBar->setVisible(false); - return numberOfFailures; -} - -int Test::checkTextResults() { - // Create lists of failed and passed tests - QStringList nameFilterFailed; - nameFilterFailed << "*.failed.txt"; - QStringList testsFailed = QDir(_snapshotDirectory).entryList(nameFilterFailed, QDir::Files, QDir::Name); - - QStringList nameFilterPassed; - nameFilterPassed << "*.passed.txt"; - QStringList testsPassed = QDir(_snapshotDirectory).entryList(nameFilterPassed, QDir::Files, QDir::Name); - - // Add results to Test Results folder - foreach(QString currentFilename, testsFailed) { - appendTestResultsToFile(currentFilename, true); - } - - foreach(QString currentFilename, testsPassed) { - appendTestResultsToFile(currentFilename, false); - } - - return testsFailed.length(); -} - -void Test::appendTestResultsToFile(TestResult testResult, QPixmap comparisonImage, bool hasFailed) { - // Critical error if Test Results folder does not exist - if (!QDir().exists(_testResultsFolderPath)) { - QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Folder " + _testResultsFolderPath + " not found"); - exit(-1); - } - - // There are separate subfolders for failures and passes - QString resultFolderPath; - if (hasFailed) { - resultFolderPath = _testResultsFolderPath + "/Failure_" + QString::number(_failureIndex) + "--" + - testResult._actualImageFilename.left(testResult._actualImageFilename.length() - 4); - - ++_failureIndex; - } else { - resultFolderPath = _testResultsFolderPath + "/Success_" + QString::number(_successIndex) + "--" + - testResult._actualImageFilename.left(testResult._actualImageFilename.length() - 4); - - ++_successIndex; - } - - if (!QDir().mkdir(resultFolderPath)) { - QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), - "Failed to create folder " + resultFolderPath); - exit(-1); - } - - QFile descriptionFile(resultFolderPath + "/" + TEST_RESULTS_FILENAME); - if (!descriptionFile.open(QIODevice::ReadWrite)) { - QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to create file " + TEST_RESULTS_FILENAME); - exit(-1); - } - - // Create text file describing the failure - QTextStream stream(&descriptionFile); - stream << "Test in folder " << testResult._pathname.left(testResult._pathname.length() - 1) << endl; // remove trailing '/' - stream << "Expected image was " << testResult._expectedImageFilename << endl; - stream << "Actual image was " << testResult._actualImageFilename << endl; - stream << "Similarity index was " << testResult._error << endl; - - descriptionFile.close(); - - // Copy expected and actual images, and save the difference image - QString sourceFile; - QString destinationFile; - - sourceFile = testResult._pathname + testResult._expectedImageFilename; - destinationFile = resultFolderPath + "/" + "Expected Image.png"; - if (!QFile::copy(sourceFile, destinationFile)) { - QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to copy " + sourceFile + " to " + destinationFile); - exit(-1); - } - - sourceFile = testResult._pathname + testResult._actualImageFilename; - destinationFile = resultFolderPath + "/" + "Actual Image.png"; - if (!QFile::copy(sourceFile, destinationFile)) { - QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to copy " + sourceFile + " to " + destinationFile); - exit(-1); - } - - comparisonImage.save(resultFolderPath + "/" + "Difference Image.png"); -} - -void::Test::appendTestResultsToFile(QString testResultFilename, bool hasFailed) { - // The test name includes everything until the penultimate period - QString testNameTemp = testResultFilename.left(testResultFilename.lastIndexOf('.')); - QString testName = testResultFilename.left(testNameTemp.lastIndexOf('.')); - QString resultFolderPath; - if (hasFailed) { - resultFolderPath = _testResultsFolderPath + "/Failure_" + QString::number(_failureIndex) + "--" + testName; - ++_failureIndex; - } else { - resultFolderPath = _testResultsFolderPath + "/Success_" + QString::number(_successIndex) + "--" + testName; - ++_successIndex; - } - - if (!QDir().mkdir(resultFolderPath)) { - QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), - "Failed to create folder " + resultFolderPath); - exit(-1); - } - - QString source = _snapshotDirectory + "/" + testResultFilename; - QString destination = resultFolderPath + "/Result.txt"; - if (!QFile::copy(source, destination)) { - QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to copy " + testResultFilename + " to " + resultFolderPath); - exit(-1); - } -} - -void Test::startTestsEvaluation(const bool isRunningFromCommandLine, - const bool isRunningInAutomaticTestRun, - const QString& snapshotDirectory, - const QString& branchFromCommandLine, - const QString& userFromCommandLine -) { - _isRunningFromCommandLine = isRunningFromCommandLine; - _isRunningInAutomaticTestRun = isRunningInAutomaticTestRun; - - if (snapshotDirectory.isNull()) { - // Get list of PNG images in folder, sorted by name - QString previousSelection = _snapshotDirectory; - QString parent = previousSelection.left(previousSelection.lastIndexOf('/')); - if (!parent.isNull() && parent.right(1) != "/") { - parent += "/"; - } - _snapshotDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder containing the snapshots", parent, - QFileDialog::ShowDirsOnly); - - // If user canceled then restore previous selection and return - if (_snapshotDirectory == "") { - _snapshotDirectory = previousSelection; - return; - } - } else { - _snapshotDirectory = snapshotDirectory; - _exitWhenComplete = (isRunningFromCommandLine && !isRunningInAutomaticTestRun); - } - - // Quit if test results folder could not be created - if (!createTestResultsFolderPath(_snapshotDirectory)) { - return; - } - - // Create two lists. The first is the test results, the second is the expected images - // The expected images are represented as a URL to enable download from GitHub - // Images that are in the wrong format are ignored. - - QStringList sortedTestResultsFilenames = createListOfAll_imagesInDirectory("png", _snapshotDirectory); - QStringList expectedImagesURLs; - - _resultImagesFullFilenames.clear(); - _expectedImagesFilenames.clear(); - _expectedImagesFullFilenames.clear(); - - QString branch = (branchFromCommandLine.isNull()) ? nitpick->getSelectedBranch() : branchFromCommandLine; - QString user = (userFromCommandLine.isNull()) ? nitpick->getSelectedUser() : userFromCommandLine; - - foreach(QString currentFilename, sortedTestResultsFilenames) { - QString fullCurrentFilename = _snapshotDirectory + "/" + currentFilename; - if (isInSnapshotFilenameFormat("png", currentFilename)) { - _resultImagesFullFilenames << fullCurrentFilename; - - QString expectedImagePartialSourceDirectory = getExpectedImagePartialSourceDirectory(currentFilename); - - // Images are stored on GitHub as ExpectedImage_ddddd.png - // Extract the digits at the end of the filename (excluding the file extension) - QString expectedImageFilenameTail = currentFilename.left(currentFilename.length() - 4).right(NUM_DIGITS); - QString expectedImageStoredFilename = EXPECTED_IMAGE_PREFIX + expectedImageFilenameTail + ".png"; - - QString imageURLString("https://raw.githubusercontent.com/" + user + "/" + GIT_HUB_REPOSITORY + "/" + branch + "/" + - expectedImagePartialSourceDirectory + "/" + expectedImageStoredFilename); - - expectedImagesURLs << imageURLString; - - // The image retrieved from GitHub needs a unique name - QString expectedImageFilename = currentFilename.replace("/", "_").replace(".png", "_EI.png"); - - _expectedImagesFilenames << expectedImageFilename; - _expectedImagesFullFilenames << _snapshotDirectory + "/" + expectedImageFilename; - } - } - - nitpick->downloadFiles(expectedImagesURLs, _snapshotDirectory, _expectedImagesFilenames, (void *)this); -} - -void Test::finishTestsEvaluation() { - // First - compare the pairs of images - int numberOfFailures = compareImageLists(); - - // Next - check text results - numberOfFailures += checkTextResults(); - - if (!_isRunningFromCommandLine && !_isRunningInAutomaticTestRun) { - if (numberOfFailures == 0) { - QMessageBox::information(0, "Success", "All images are as expected"); - } else { - QMessageBox::information(0, "Failure", "One or more images are not as expected"); - } - } - - QString zippedFolderName = zipAndDeleteTestResultsFolder(); - - if (_exitWhenComplete) { - exit(0); - } - - if (_isRunningInAutomaticTestRun) { - nitpick->automaticTestRunEvaluationComplete(zippedFolderName, numberOfFailures); - } -} - -bool Test::isAValidDirectory(const QString& pathname) { - // Only process directories - QDir dir(pathname); - if (!dir.exists()) { - return false; - } - - // Ignore '.', '..' directories - if (pathname[pathname.length() - 1] == '.') { - return false; - } - - return true; -} - -QString Test::extractPathFromTestsDown(const QString& fullPath) { - // `fullPath` includes the full path to the test. We need the portion below (and including) `tests` - QStringList pathParts = fullPath.split('/'); - int i{ 0 }; - while (i < pathParts.length() && pathParts[i] != "tests") { - ++i; - } - - if (i == pathParts.length()) { - QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Bad testPathname"); - exit(-1); - } - - QString partialPath; - for (int j = i; j < pathParts.length(); ++j) { - partialPath += "/" + pathParts[j]; - } - - return partialPath; -} - -void Test::includeTest(QTextStream& textStream, const QString& testPathname) { - QString partialPath = extractPathFromTestsDown(testPathname); - QString partialPathWithoutTests = partialPath.right(partialPath.length() - 7); - - textStream << "Script.include(testsRootPath + \"" << partialPathWithoutTests + "\");" << endl; -} - -void Test::createTests(const QString& clientProfile) { - // Rename files sequentially, as ExpectedResult_00000.png, ExpectedResult_00001.png and so on - // Any existing expected result images will be deleted - QString previousSelection = _snapshotDirectory; - QString parent = previousSelection.left(previousSelection.lastIndexOf('/')); - if (!parent.isNull() && parent.right(1) != "/") { - parent += "/"; - } - - _snapshotDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder containing the snapshots", parent, - QFileDialog::ShowDirsOnly); - - // If user canceled then restore previous selection and return - if (_snapshotDirectory == "") { - _snapshotDirectory = previousSelection; - return; - } - - previousSelection = _testsRootDirectory; - parent = previousSelection.left(previousSelection.lastIndexOf('/')); - if (!parent.isNull() && parent.right(1) != "/") { - parent += "/"; - } - - _testsRootDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select test root folder", parent, - QFileDialog::ShowDirsOnly); - - // If user canceled then restore previous selection and return - if (_testsRootDirectory == "") { - _testsRootDirectory = previousSelection; - return; - } - - QStringList sortedImageFilenames = createListOfAll_imagesInDirectory("png", _snapshotDirectory); - - int i = 1; - const int maxImages = pow(10, NUM_DIGITS); - foreach (QString currentFilename, sortedImageFilenames) { - QString fullCurrentFilename = _snapshotDirectory + "/" + currentFilename; - if (isInSnapshotFilenameFormat("png", currentFilename)) { - if (i >= maxImages) { - QMessageBox::critical(0, "Error", "More than " + QString::number(maxImages) + " images not supported"); - exit(-1); - } - - // Path to test is extracted from the file name - // Example: - // filename is tests.engine.interaction.pointer.laser.distanceScaleEnd.00000.jpg - // path is <_testDirectory>/engine/interaction/pointer/laser/distanceScaleEnd - // - // Note: we don't use the first part and the last 2 parts of the filename at this stage - // - QStringList pathParts = currentFilename.split("."); - QString fullNewFileName = _testsRootDirectory; - for (int j = 1; j < pathParts.size() - 2; ++j) { - fullNewFileName += "/" + pathParts[j]; - } - - // The image _index is the penultimate component of the path parts (the last being the file extension) - QString newFilename = "ExpectedImage_" + pathParts[pathParts.size() - 2].rightJustified(5, '0') + ".png"; - fullNewFileName += "/" + newFilename; - - try { - if (QFile::exists(fullNewFileName)) { - QFile::remove(fullNewFileName); - } - QFile::copy(fullCurrentFilename, fullNewFileName); - } catch (...) { - QMessageBox::critical(0, "Error", "Could not copy file: " + fullCurrentFilename + " to " + fullNewFileName + "\n"); - exit(-1); - } - ++i; - } - } - - QMessageBox::information(0, "Success", "Test images have been created"); -} - -ExtractedText Test::getTestScriptLines(QString testFileName) { - ExtractedText relevantTextFromTest; - - QFile inputFile(testFileName); - inputFile.open(QIODevice::ReadOnly); - if (!inputFile.isOpen()) { - QMessageBox::critical(0, - "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), - "Failed to open \"" + testFileName - ); - } - - QTextStream stream(&inputFile); - QString line = stream.readLine(); - - // Name of test is the string in the following line: - // nitpick.perform("Apply Material Entities to Avatars", Script.resolvePath("."), function(testType) {... - const QString ws("\\h*"); //white-space character - const QString functionPerformName(ws + "nitpick" + ws + "\\." + ws + "perform"); - const QString quotedString("\\\".+\\\""); - QString regexTestTitle(ws + functionPerformName + "\\(" + quotedString); - QRegularExpression lineContainingTitle = QRegularExpression(regexTestTitle); - - - // Each step is either of the following forms: - // nitpick.addStepSnapshot("Take snapshot"... - // nitpick.addStep("Clean up after test"... - const QString functionAddStepSnapshotName(ws + "nitpick" + ws + "\\." + ws + "addStepSnapshot"); - const QString regexStepSnapshot(ws + functionAddStepSnapshotName + ws + "\\(" + ws + quotedString + ".*"); - const QRegularExpression lineStepSnapshot = QRegularExpression(regexStepSnapshot); - - const QString functionAddStepName(ws + "nitpick" + ws + "\\." + ws + "addStep"); - const QString regexStep(ws + functionAddStepName + ws + "\\(" + ws + quotedString + ".*"); - const QRegularExpression lineStep = QRegularExpression(regexStep); - - while (!line.isNull()) { - line = stream.readLine(); - if (lineContainingTitle.match(line).hasMatch()) { - QStringList tokens = line.split('"'); - relevantTextFromTest.title = tokens[1]; - } else if (lineStepSnapshot.match(line).hasMatch()) { - QStringList tokens = line.split('"'); - QString nameOfStep = tokens[1]; - - Step *step = new Step(); - step->text = nameOfStep; - step->takeSnapshot = true; - relevantTextFromTest.stepList.emplace_back(step); - - } else if (lineStep.match(line).hasMatch()) { - QStringList tokens = line.split('"'); - QString nameOfStep = tokens[1]; - - Step *step = new Step(); - step->text = nameOfStep; - step->takeSnapshot = false; - relevantTextFromTest.stepList.emplace_back(step); - } - } - - inputFile.close(); - - return relevantTextFromTest; -} - -bool Test::createFileSetup() { - // Folder selection - QString previousSelection = _testDirectory; - QString parent = previousSelection.left(previousSelection.lastIndexOf('/')); - if (!parent.isNull() && parent.right(1) != "/") { - parent += "/"; - } - - _testDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder containing the test", parent, - QFileDialog::ShowDirsOnly); - - // If user canceled then restore previous selection and return - if (_testDirectory == "") { - _testDirectory = previousSelection; - return false; - } - - return true; -} - -bool Test::createAllFilesSetup() { - // Select folder to start recursing from - QString previousSelection = _testsRootDirectory; - QString parent = previousSelection.left(previousSelection.lastIndexOf('/')); - if (!parent.isNull() && parent.right(1) != "/") { - parent += "/"; - } - - _testsRootDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select the tests root folder", parent, - QFileDialog::ShowDirsOnly); - - // If user cancelled then restore previous selection and return - if (_testsRootDirectory == "") { - _testsRootDirectory = previousSelection; - return false; - } - - return true; -} - -// Create an MD file for a user-selected test. -// The folder selected must contain a script named "test.js", the file produced is named "test.md" -void Test::createMDFile() { - if (!createFileSetup()) { - return; - } - - if (createMDFile(_testDirectory)) { - QMessageBox::information(0, "Success", "MD file has been created"); - } -} - -void Test::createAllMDFiles() { - if (!createAllFilesSetup()) { - return; - } - - // First test if top-level folder has a test.js file - const QString testPathname{ _testsRootDirectory + "/" + TEST_FILENAME }; - QFileInfo fileInfo(testPathname); - if (fileInfo.exists()) { - createMDFile(_testsRootDirectory); - } - - QDirIterator it(_testsRootDirectory, QDirIterator::Subdirectories); - while (it.hasNext()) { - QString directory = it.next(); - - // Only process directories - QDir dir; - if (!isAValidDirectory(directory)) { - continue; - } - - const QString testPathname{ directory + "/" + TEST_FILENAME }; - QFileInfo fileInfo(testPathname); - if (fileInfo.exists()) { - createMDFile(directory); - } - } - - QMessageBox::information(0, "Success", "MD files have been created"); -} - -bool Test::createMDFile(const QString& directory) { - // Verify folder contains test.js file - QString testFileName(directory + "/" + TEST_FILENAME); - QFileInfo testFileInfo(testFileName); - if (!testFileInfo.exists()) { - QMessageBox::critical(0, "Error", "Could not find file: " + TEST_FILENAME); - return false; - } - - ExtractedText testScriptLines = getTestScriptLines(testFileName); - - QString mdFilename(directory + "/" + "test.md"); - QFile mdFile(mdFilename); - if (!mdFile.open(QIODevice::WriteOnly)) { - QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to create file " + mdFilename); - exit(-1); - } - - QTextStream stream(&mdFile); - - //Test title - QString testName = testScriptLines.title; - stream << "# " << testName << "\n"; - - stream << "## Run this script URL: [Manual](./test.js?raw=true) [Auto](./testAuto.js?raw=true)(from menu/Edit/Open and Run scripts from URL...)." << "\n\n"; - - stream << "## Preconditions" << "\n"; - stream << "- In an empty region of a domain with editing rights." << "\n\n"; - - stream << "## Steps\n"; - stream << "Press '" + ADVANCE_KEY + "' key to advance step by step\n\n"; // note apostrophes surrounding 'ADVANCE_KEY' - - int snapShotIndex { 0 }; - for (size_t i = 0; i < testScriptLines.stepList.size(); ++i) { - stream << "### Step " << QString::number(i + 1) << "\n"; - stream << "- " << testScriptLines.stepList[i]->text << "\n"; - if ((i + 1 < testScriptLines.stepList.size()) && testScriptLines.stepList[i]->takeSnapshot) { - stream << "- ![](./ExpectedImage_" << QString::number(snapShotIndex).rightJustified(5, '0') << ".png)\n"; - ++snapShotIndex; - } - } - - mdFile.close(); - - foreach (auto test, testScriptLines.stepList) { - delete test; - } - testScriptLines.stepList.clear(); - - return true; -} - -void Test::createTestAutoScript() { - if (!createFileSetup()) { - return; - } - - if (createTestAutoScript(_testDirectory)) { - QMessageBox::information(0, "Success", "'testAuto.js` script has been created"); - } -} - -void Test::createAllTestAutoScripts() { - if (!createAllFilesSetup()) { - return; - } - - // First test if top-level folder has a test.js file - const QString testPathname{ _testsRootDirectory + "/" + TEST_FILENAME }; - QFileInfo fileInfo(testPathname); - if (fileInfo.exists()) { - createTestAutoScript(_testsRootDirectory); - } - - QDirIterator it(_testsRootDirectory, QDirIterator::Subdirectories); - while (it.hasNext()) { - QString directory = it.next(); - - // Only process directories - QDir dir; - if (!isAValidDirectory(directory)) { - continue; - } - - const QString testPathname{ directory + "/" + TEST_FILENAME }; - QFileInfo fileInfo(testPathname); - if (fileInfo.exists()) { - createTestAutoScript(directory); - } - } - - QMessageBox::information(0, "Success", "All 'testAuto.js' scripts have been created"); -} - -bool Test::createTestAutoScript(const QString& directory) { - // Verify folder contains test.js file - QString testFileName(directory + "/" + TEST_FILENAME); - QFileInfo testFileInfo(testFileName); - if (!testFileInfo.exists()) { - QMessageBox::critical(0, "Error", "Could not find file: " + TEST_FILENAME); - return false; - } - - QString testAutoScriptFilename(directory + "/" + "testAuto.js"); - QFile testAutoScriptFile(testAutoScriptFilename); - if (!testAutoScriptFile.open(QIODevice::WriteOnly)) { - QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), - "Failed to create file " + testAutoScriptFilename); - exit(-1); - } - - QTextStream stream(&testAutoScriptFile); - - stream << "if (typeof PATH_TO_THE_REPO_PATH_UTILS_FILE === 'undefined') PATH_TO_THE_REPO_PATH_UTILS_FILE = 'https://raw.githubusercontent.com/highfidelity/hifi_tests/master/tests/utils/branchUtils.js';\n"; - stream << "Script.include(PATH_TO_THE_REPO_PATH_UTILS_FILE);\n"; - stream << "var nitpick = createNitpick(Script.resolvePath('.'));\n\n"; - stream << "nitpick.enableAuto();\n\n"; - stream << "Script.include('./test.js?raw=true');\n"; - - testAutoScriptFile.close(); - return true; -} - -// Creates a single script in a user-selected folder. -// This script will run all text.js scripts in every applicable sub-folder -void Test::createRecursiveScript() { - if (!createFileSetup()) { - return; - } - - createRecursiveScript(_testDirectory, true); - QMessageBox::information(0, "Success", "'testRecursive.js` script has been created"); -} - -// This method creates a `testRecursive.js` script in every sub-folder. -void Test::createAllRecursiveScripts() { - if (!createAllFilesSetup()) { - return; - } - - createAllRecursiveScripts(_testsRootDirectory); - createRecursiveScript(_testsRootDirectory, false); - QMessageBox::information(0, "Success", "Scripts have been created"); -} - -void Test::createAllRecursiveScripts(const QString& directory) { - QDirIterator it(directory, QDirIterator::Subdirectories); - - while (it.hasNext()) { - QString nextDirectory = it.next(); - if (isAValidDirectory(nextDirectory)) { - createAllRecursiveScripts(nextDirectory); - createRecursiveScript(nextDirectory, false); - } - } -} - -void Test::createRecursiveScript(const QString& directory, bool interactiveMode) { - // If folder contains a test, then we are at a leaf - const QString testPathname{ directory + "/" + TEST_FILENAME }; - if (QFileInfo(testPathname).exists()) { - return; - } - - // Directories are included in reverse order. The nitpick scripts use a stack mechanism, - // so this ensures that the tests run in alphabetical order (a convenience when debugging) - QStringList directories; - QDirIterator it(directory); - while (it.hasNext()) { - QString subDirectory = it.next(); - - // Only process directories - if (!isAValidDirectory(subDirectory)) { - continue; - } - - const QString testPathname{ subDirectory + "/" + TEST_FILENAME }; - if (QFileInfo(testPathname).exists()) { - // Current folder contains a test script - directories.push_front(testPathname); - } - - const QString testRecursivePathname{ subDirectory + "/" + TEST_RECURSIVE_FILENAME }; - if (QFileInfo(testRecursivePathname).exists()) { - // Current folder contains a recursive script - directories.push_front(testRecursivePathname); - } - } - - // If 'directories' is empty, this means that this recursive script has no tests to call, so it is redundant - if (directories.length() == 0) { - return; - } - - // Open the recursive script file - const QString recursiveTestsFilename(directory + "/" + TEST_RECURSIVE_FILENAME); - QFile recursiveTestsFile(recursiveTestsFilename); - if (!recursiveTestsFile.open(QIODevice::WriteOnly | QIODevice::Text)) { - QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), - "Failed to create \"" + TEST_RECURSIVE_FILENAME + "\" in directory \"" + directory + "\""); - - exit(-1); - } - - QTextStream textStream(&recursiveTestsFile); - - textStream << "// This is an automatically generated file, created by nitpick" << endl; - - // Include 'nitpick.js' - QString branch = nitpick->getSelectedBranch(); - QString user = nitpick->getSelectedUser(); - - textStream << "PATH_TO_THE_REPO_PATH_UTILS_FILE = \"https://raw.githubusercontent.com/" + user + "/hifi_tests/" + branch + - "/tests/utils/branchUtils.js\";" - << endl; - textStream << "Script.include(PATH_TO_THE_REPO_PATH_UTILS_FILE);" << endl << endl; - - // The 'depth' variable is used to signal when to start running the recursive scripts - textStream << "if (typeof depth === 'undefined') {" << endl; - textStream << " depth = 0;" << endl; - textStream << " nitpick = createNitpick(Script.resolvePath(\".\"));" << endl; - textStream << " testsRootPath = nitpick.getTestsRootPath();" << endl << endl; - textStream << " nitpick.enableRecursive();" << endl; - textStream << " nitpick.enableAuto();" << endl; - textStream << "} else {" << endl; - textStream << " depth++" << endl; - textStream << "}" << endl << endl; - - // Now include the test scripts - for (int i = 0; i < directories.length(); ++i) { - includeTest(textStream, directories.at(i)); - } - - textStream << endl; - textStream << "if (depth > 0) {" << endl; - textStream << " depth--;" << endl; - textStream << "} else {" << endl; - textStream << " nitpick.runRecursive();" << endl; - textStream << "}" << endl << endl; - - recursiveTestsFile.close(); -} - -void Test::createTestsOutline() { - QString previousSelection = _testDirectory; - QString parent = previousSelection.left(previousSelection.lastIndexOf('/')); - if (!parent.isNull() && parent.right(1) != "/") { - parent += "/"; - } - - _testDirectory = - QFileDialog::getExistingDirectory(nullptr, "Please select the tests root folder", parent, QFileDialog::ShowDirsOnly); - - // If user canceled then restore previous selection and return - if (_testDirectory == "") { - _testDirectory = previousSelection; - return; - } - - const QString testsOutlineFilename { "testsOutline.md" }; - QString mdFilename(_testDirectory + "/" + testsOutlineFilename); - QFile mdFile(mdFilename); - if (!mdFile.open(QIODevice::WriteOnly)) { - QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to create file " + mdFilename); - exit(-1); - } - - QTextStream stream(&mdFile); - - //Test title - stream << "# Outline of all tests\n"; - stream << "Directories with an appended (*) have an automatic test\n\n"; - - // We need to know our current depth, as this isn't given by QDirIterator - int rootDepth { _testDirectory.count('/') }; - - // Each test is shown as the folder name linking to the matching GitHub URL, and the path to the associated test.md file - QDirIterator it(_testDirectory, QDirIterator::Subdirectories); - while (it.hasNext()) { - QString directory = it.next(); - - // Only process directories - if (!isAValidDirectory(directory)) { - continue; - } - - // Ignore the utils directory - if (directory.right(5) == "utils") { - continue; - } - - // The prefix is the MarkDown prefix needed for correct indentation - // It consists of 2 spaces for each level of indentation, folled by a dash sign - int currentDepth = directory.count('/') - rootDepth; - QString prefix = QString(" ").repeated(2 * currentDepth - 1) + " - "; - - // The directory name appears after the last slash (we are assured there is at least 1). - QString directoryName = directory.right(directory.length() - directory.lastIndexOf("/") - 1); - - // nitpick is run on a clone of the repository. We use relative paths, so we can use both local disk and GitHub - // For a test in "D:/GitHub/hifi_tests/tests/content/entity/zone/ambientLightInheritance" the - // GitHub URL is "./content/entity/zone/ambientLightInheritance?raw=true" - QString partialPath = directory.right(directory.length() - (directory.lastIndexOf("/tests/") + QString("/tests").length() + 1)); - QString url = "./" + partialPath; - - stream << prefix << "[" << directoryName << "](" << url << "?raw=true" << ")"; - - // note that md files may be named 'test.md' or 'testStory.md' - QFileInfo fileInfo1(directory + "/test.md"); - if (fileInfo1.exists()) { - stream << " [(test description)](" << url << "/test.md)"; - } - - QFileInfo fileInfo2(directory + "/testStory.md"); - if (fileInfo2.exists()) { - stream << " [(test description)](" << url << "/testStory.md)"; - } - - QFileInfo fileInfo3(directory + "/" + TEST_FILENAME); - if (fileInfo3.exists()) { - stream << " (*)"; - } - stream << "\n"; - } - - mdFile.close(); - - QMessageBox::information(0, "Success", "Test outline file " + testsOutlineFilename + " has been created"); -} - -void Test::createTestRailTestCases() { - QString previousSelection = _testDirectory; - QString parent = previousSelection.left(previousSelection.lastIndexOf('/')); - if (!parent.isNull() && parent.right(1) != "/") { - parent += "/"; - } - - _testDirectory = - QFileDialog::getExistingDirectory(nullptr, "Please select the tests root folder", parent, QFileDialog::ShowDirsOnly); - - // If user cancelled then restore previous selection and return - if (_testDirectory.isNull()) { - _testDirectory = previousSelection; - return; - } - - QString outputDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select a folder to store generated files in", - nullptr, QFileDialog::ShowDirsOnly); - - // If user cancelled then return - if (outputDirectory.isNull()) { - return; - } - - if (!_testRailInterface) { - _testRailInterface = new TestRailInterface; - } - - if (_testRailCreateMode == PYTHON) { - _testRailInterface->createTestSuitePython(_testDirectory, outputDirectory, nitpick->getSelectedUser(), - nitpick->getSelectedBranch()); - } else { - _testRailInterface->createTestSuiteXML(_testDirectory, outputDirectory, nitpick->getSelectedUser(), - nitpick->getSelectedBranch()); - } -} - -void Test::createTestRailRun() { - QString outputDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select a folder to store generated files in", - nullptr, QFileDialog::ShowDirsOnly); - - if (outputDirectory.isNull()) { - return; - } - - - if (!_testRailInterface) { - _testRailInterface = new TestRailInterface; - } - - _testRailInterface->createTestRailRun(outputDirectory); -} - -void Test::updateTestRailRunResult() { - QString testResults = QFileDialog::getOpenFileName(nullptr, "Please select the zipped test results to update from", nullptr, - "Zipped Test Results (*.zip)"); - if (testResults.isNull()) { - return; - } - - QString tempDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select a folder to store temporary files in", - nullptr, QFileDialog::ShowDirsOnly); - if (tempDirectory.isNull()) { - return; - } - - - if (!_testRailInterface) { - _testRailInterface = new TestRailInterface; - } - - _testRailInterface->updateTestRailRunResults(testResults, tempDirectory); -} - -QStringList Test::createListOfAll_imagesInDirectory(const QString& imageFormat, const QString& pathToImageDirectory) { - _imageDirectory = QDir(pathToImageDirectory); - QStringList nameFilters; - nameFilters << "*." + imageFormat; - - return _imageDirectory.entryList(nameFilters, QDir::Files, QDir::Name); -} - -// Snapshots are files in the following format: -// Filename (i.e. without extension) contains tests (this is based on all test scripts being within the tests folder) -// Last 5 characters in filename are digits (after removing the extension) -// Extension is 'imageFormat' -bool Test::isInSnapshotFilenameFormat(const QString& imageFormat, const QString& filename) { - bool contains_tests = filename.contains("tests" + PATH_SEPARATOR); - - QString filenameWithoutExtension = filename.left(filename.lastIndexOf('.')); - bool last5CharactersAreDigits; - filenameWithoutExtension.right(5).toInt(&last5CharactersAreDigits, 10); - - bool extensionIsIMAGE_FORMAT = (filename.right(imageFormat.length()) == imageFormat); - - return (contains_tests && last5CharactersAreDigits && extensionIsIMAGE_FORMAT); -} - -// For a file named "D_GitHub_hifi-tests_tests_content_entity_zone_create_0.jpg", the test directory is -// D:/GitHub/hifi-tests/tests/content/entity/zone/create -// This method assumes the filename is in the correct format -QString Test::getExpectedImageDestinationDirectory(const QString& filename) { - QString filenameWithoutExtension = filename.left(filename.length() - 4); - QStringList filenameParts = filenameWithoutExtension.split(PATH_SEPARATOR); - - QString result = filenameParts[0] + ":"; - - for (int i = 1; i < filenameParts.length() - 1; ++i) { - result += "/" + filenameParts[i]; - } - - return result; -} - -// For a file named "D_GitHub_hifi-tests_tests_content_entity_zone_create_0.jpg", the source directory on GitHub -// is ...tests/content/entity/zone/create -// This is used to create the full URL -// This method assumes the filename is in the correct format -QString Test::getExpectedImagePartialSourceDirectory(const QString& filename) { - QString filenameWithoutExtension = filename.left(filename.length() - 4); - QStringList filenameParts = filenameWithoutExtension.split(PATH_SEPARATOR); - - // Note that the bottom-most "tests" folder is assumed to be the root - // This is required because the tests folder is named hifi_tests - int i { filenameParts.length() - 1 }; - while (i >= 0 && filenameParts[i] != "tests") { - --i; - } - - if (i < 0) { - QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Bad filename"); - exit(-1); - } - - QString result = filenameParts[i]; - - for (int j = i + 1; j < filenameParts.length() - 1; ++j) { - result += "/" + filenameParts[j]; - } - - return result; -} - -void Test::setTestRailCreateMode(TestRailCreateMode testRailCreateMode) { - _testRailCreateMode = testRailCreateMode; -} - -void Test::createWebPage(QCheckBox* updateAWSCheckBox, QLineEdit* urlLineEdit) { - QString testResults = QFileDialog::getOpenFileName(nullptr, "Please select the zipped test results to update from", nullptr, - "Zipped Test Results (TestResults--*.zip)"); - if (testResults.isNull()) { - return; - } - - QString workingDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select a folder to store temporary files in", - nullptr, QFileDialog::ShowDirsOnly); - if (workingDirectory.isNull()) { - return; - } - - if (!_awsInterface) { - _awsInterface = new AWSInterface; - } - - _awsInterface->createWebPageFromResults(testResults, workingDirectory, updateAWSCheckBox, urlLineEdit); -} \ No newline at end of file diff --git a/tools/nitpick/src/Test.h b/tools/nitpick/src/Test.h deleted file mode 100644 index 23011d0c31..0000000000 --- a/tools/nitpick/src/Test.h +++ /dev/null @@ -1,168 +0,0 @@ -// -// Test.h -// -// Created by Nissim Hadar on 2 Nov 2017. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_test_h -#define hifi_test_h - -#include -#include -#include -#include - -#include "AWSInterface.h" -#include "ImageComparer.h" -#include "MismatchWindow.h" -#include "TestRailInterface.h" - -class Step { -public: - QString text; - bool takeSnapshot; -}; - -using StepList = std::vector; - -class ExtractedText { -public: - QString title; - StepList stepList; -}; - -enum TestRailCreateMode { - PYTHON, - XML -}; - -class Test { -public: - Test(QProgressBar* progressBar, QCheckBox* checkBoxInteractiveMode); - - void startTestsEvaluation(const bool isRunningFromCommandLine, - const bool isRunningInAutomaticTestRun, - const QString& snapshotDirectory = QString(), - const QString& branchFromCommandLine = QString(), - const QString& userFromCommandLine = QString()); - - void finishTestsEvaluation(); - - void createTests(const QString& clientProfile); - - void createTestsOutline(); - - bool createFileSetup(); - bool createAllFilesSetup(); - - void createMDFile(); - void createAllMDFiles(); - bool createMDFile(const QString& directory); - - void createTestAutoScript(); - void createAllTestAutoScripts(); - bool createTestAutoScript(const QString& directory); - - void createTestRailTestCases(); - void createTestRailRun(); - - void updateTestRailRunResult(); - - void createAllRecursiveScripts(); - void createAllRecursiveScripts(const QString& directory); - - void createRecursiveScript(); - void createRecursiveScript(const QString& directory, bool interactiveMode); - - int compareImageLists(); - int checkTextResults(); - - QStringList createListOfAll_imagesInDirectory(const QString& imageFormat, const QString& pathToImageDirectory); - - bool isInSnapshotFilenameFormat(const QString& imageFormat, const QString& filename); - - void includeTest(QTextStream& textStream, const QString& testPathname); - - void appendTestResultsToFile(TestResult testResult, QPixmap comparisonImage, bool hasFailed); - void appendTestResultsToFile(QString testResultFilename, bool hasFailed); - - bool createTestResultsFolderPath(const QString& directory); - QString zipAndDeleteTestResultsFolder(); - - static bool isAValidDirectory(const QString& pathname); - QString extractPathFromTestsDown(const QString& fullPath); - QString getExpectedImageDestinationDirectory(const QString& filename); - QString getExpectedImagePartialSourceDirectory(const QString& filename); - - ExtractedText getTestScriptLines(QString testFileName); - - void setTestRailCreateMode(TestRailCreateMode testRailCreateMode); - - void createWebPage(QCheckBox* updateAWSCheckBox, QLineEdit* urlLineEdit); - -private: - QProgressBar* _progressBar; - QCheckBox* _checkBoxInteractiveMode; - - bool _isRunningFromCommandLine{ false }; - bool _isRunningInAutomaticTestRun{ false }; - - const QString TEST_FILENAME{ "test.js" }; - const QString TEST_RECURSIVE_FILENAME{ "testRecursive.js" }; - const QString TEST_RESULTS_FOLDER { "TestResults" }; - const QString TEST_RESULTS_FILENAME { "TestResults.txt" }; - - const double THRESHOLD{ 0.935 }; - - QDir _imageDirectory; - - MismatchWindow _mismatchWindow; - - ImageComparer _imageComparer; - - QString _testResultsFolderPath; - int _failureIndex{ 1 }; - int _successIndex{ 1 }; - - // Expected images are in the format ExpectedImage_dddd.jpg (d == decimal digit) - const int NUM_DIGITS { 5 }; - const QString EXPECTED_IMAGE_PREFIX { "ExpectedImage_" }; - - // We have two directories to work with. - // The first is the directory containing the test we are working with - // The second is the root directory of all tests - // The third contains the snapshots taken for test runs that need to be evaluated - QString _testDirectory; - QString _testsRootDirectory; - QString _snapshotDirectory; - - QStringList _expectedImagesFilenames; - QStringList _expectedImagesFullFilenames; - QStringList _resultImagesFullFilenames; - - // Used for accessing GitHub - const QString GIT_HUB_DEFAULT_USER{ "highfidelity" }; - const QString GIT_HUB_DEFAULT_BRANCH{ "master" }; - const QString GIT_HUB_REPOSITORY{ "hifi_tests" }; - - const QString DATETIME_FORMAT{ "yyyy-MM-dd_hh-mm-ss" }; - - // NOTE: these need to match the appropriate var's in nitpick.js - // var advanceKey = "n"; - // var pathSeparator = "."; - const QString ADVANCE_KEY{ "n" }; - const QString PATH_SEPARATOR{ "." }; - - bool _exitWhenComplete{ false }; - - TestRailInterface* _testRailInterface; - TestRailCreateMode _testRailCreateMode { PYTHON }; - - AWSInterface* _awsInterface; -}; - -#endif // hifi_test_h \ No newline at end of file diff --git a/tools/nitpick/src/TestRailInterface.cpp b/tools/nitpick/src/TestRailInterface.cpp index 6ed13a72b6..8b8803153f 100644 --- a/tools/nitpick/src/TestRailInterface.cpp +++ b/tools/nitpick/src/TestRailInterface.cpp @@ -9,7 +9,7 @@ // #include "TestRailInterface.h" -#include "Test.h" +#include "TestCreator.h" #include #include @@ -258,7 +258,7 @@ bool TestRailInterface::requestTestRailResultsDataFromUser() { } bool TestRailInterface::isAValidTestDirectory(const QString& directory) { - if (Test::isAValidDirectory(directory)) { + if (TestCreator::isAValidDirectory(directory)) { // Ignore the utils and preformance directories if (directory.right(QString("utils").length()) == "utils" || directory.right(QString("performance").length()) == "performance") { diff --git a/tools/nitpick/src/TestRunner.cpp b/tools/nitpick/src/TestRunner.cpp index 54246de80b..c4e991e5ee 100644 --- a/tools/nitpick/src/TestRunner.cpp +++ b/tools/nitpick/src/TestRunner.cpp @@ -14,6 +14,26 @@ #include "Nitpick.h" extern Nitpick* nitpick; +TestRunner::TestRunner( + QLabel* workingFolderLabel, + QLabel* statusLabel, + QCheckBox* usePreviousInstallationCheckBox, + QCheckBox* runLatest, + QLineEdit* url, + QCheckBox* runFullSuite, + QLineEdit* scriptURL +) { + _workingFolderLabel = workingFolderLabel; + _statusLabel = statusLabel; + _usePreviousInstallationCheckBox = usePreviousInstallationCheckBox; + _runLatest = runLatest; + _url = url; + _runFullSuite = runFullSuite; + _scriptURL = scriptURL; + + _downloader = new Downloader(); +} + void TestRunner::setWorkingFolder(QLabel* workingFolderLabel) { // Everything will be written to this folder QString previousSelection = _workingFolder; @@ -49,7 +69,7 @@ void TestRunner::downloadBuildXml(void* caller) { urls << DEV_BUILD_XML_URL; filenames << DEV_BUILD_XML_FILENAME; - nitpick->downloadFiles(urls, _workingFolder, filenames, caller); + _downloader->downloadFiles(urls, _workingFolder, filenames, caller); } void TestRunner::parseBuildInformation() { diff --git a/tools/nitpick/src/TestRunner.h b/tools/nitpick/src/TestRunner.h index d2468ec2fa..6d36f246f7 100644 --- a/tools/nitpick/src/TestRunner.h +++ b/tools/nitpick/src/TestRunner.h @@ -11,6 +11,8 @@ #ifndef hifi_testRunner_h #define hifi_testRunner_h +#include "Downloader.h" + #include #include #include @@ -28,7 +30,18 @@ public: class TestRunner { public: + TestRunner( + QLabel* workingFolderLabel, + QLabel* statusLabel, + QCheckBox* usePreviousInstallationOnMobileCheckBox, + QCheckBox* runLatest, + QLineEdit* url, + QCheckBox* runFullSuite, + QLineEdit* scriptURL + ); + void setWorkingFolder(QLabel* workingFolderLabel); + void downloadBuildXml(void* caller); void parseBuildInformation(); QString getInstallerNameFromURL(const QString& url); @@ -36,10 +49,15 @@ public: void appendLog(const QString& message); protected: + Downloader* _downloader; + QLabel* _workingFolderLabel; QLabel* _statusLabel; - QLineEdit* _url; + QCheckBox* _usePreviousInstallationCheckBox; QCheckBox* _runLatest; + QLineEdit* _url; + QCheckBox* _runFullSuite; + QLineEdit* _scriptURL; QString _workingFolder; diff --git a/tools/nitpick/src/TestRunnerDesktop.cpp b/tools/nitpick/src/TestRunnerDesktop.cpp index e45d895886..b9caaa0ecb 100644 --- a/tools/nitpick/src/TestRunnerDesktop.cpp +++ b/tools/nitpick/src/TestRunnerDesktop.cpp @@ -27,23 +27,22 @@ TestRunnerDesktop::TestRunnerDesktop( std::vector timeEdits, QLabel* workingFolderLabel, QCheckBox* runServerless, + QCheckBox* usePreviousInstallationOnMobileCheckBox, QCheckBox* runLatest, QLineEdit* url, + QCheckBox* runFullSuite, + QLineEdit* scriptURL, QPushButton* runNow, QLabel* statusLabel, QObject* parent -) : QObject(parent) +) : QObject(parent), TestRunner(workingFolderLabel, statusLabel, usePreviousInstallationOnMobileCheckBox, runLatest, url, runFullSuite, scriptURL) { _dayCheckboxes = dayCheckboxes; _timeEditCheckboxes = timeEditCheckboxes; _timeEdits = timeEdits; - _workingFolderLabel = workingFolderLabel; _runServerless = runServerless; - _runLatest = runLatest; - _url = url; _runNow = runNow; - _statusLabel = statusLabel; _installerThread = new QThread(); _installerWorker = new InstallerWorker(); @@ -179,10 +178,14 @@ void TestRunnerDesktop::run() { // This will be restored at the end of the tests saveExistingHighFidelityAppDataFolder(); - _statusLabel->setText("Downloading Build XML"); - downloadBuildXml((void*)this); + if (_usePreviousInstallationCheckBox->isChecked()) { + installationComplete(); + } else { + _statusLabel->setText("Downloading Build XML"); + downloadBuildXml((void*)this); - // `downloadComplete` will run after download has completed + downloadComplete(); + } } void TestRunnerDesktop::downloadComplete() { @@ -209,9 +212,9 @@ void TestRunnerDesktop::downloadComplete() { _statusLabel->setText("Downloading installer"); - nitpick->downloadFiles(urls, _workingFolder, filenames, (void*)this); + _downloader->downloadFiles(urls, _workingFolder, filenames, (void*)this); - // `downloadComplete` will run again after download has completed + downloadComplete(); } else { // Download of Installer has completed @@ -292,15 +295,19 @@ void TestRunnerDesktop::installationComplete() { void TestRunnerDesktop::verifyInstallationSucceeded() { // Exit if the executables are missing. - // On Windows, the reason is probably that UAC has blocked the installation. This is treated as a critical error #ifdef Q_OS_WIN QFileInfo interfaceExe(QDir::toNativeSeparators(_installationFolder) + "\\interface.exe"); QFileInfo assignmentClientExe(QDir::toNativeSeparators(_installationFolder) + "\\assignment-client.exe"); QFileInfo domainServerExe(QDir::toNativeSeparators(_installationFolder) + "\\domain-server.exe"); if (!interfaceExe.exists() || !assignmentClientExe.exists() || !domainServerExe.exists()) { - QMessageBox::critical(0, "Installation of High Fidelity has failed", "Please verify that UAC has been disabled"); - exit(-1); + if (_runLatest->isChecked()) { + // On Windows, the reason is probably that UAC has blocked the installation. This is treated as a critical error + QMessageBox::critical(0, "Installation of High Fidelity has failed", "Please verify that UAC has been disabled"); + exit(-1); + } else { + QMessageBox::critical(0, "Installation of High Fidelity not found", "Please verify that working folder contains a proper installation"); + } } #endif } @@ -457,8 +464,9 @@ void TestRunnerDesktop::runInterfaceWithTestScript() { QString deleteScript = QString("https://raw.githubusercontent.com/") + _user + "/hifi_tests/" + _branch + "/tests/utils/deleteNearbyEntities.js"; - QString testScript = - QString("https://raw.githubusercontent.com/") + _user + "/hifi_tests/" + _branch + "/tests/testRecursive.js"; + QString testScript = (_runFullSuite->isChecked()) + ? QString("https://raw.githubusercontent.com/") + _user + "/hifi_tests/" + _branch + "/tests/testRecursive.js" + : _scriptURL->text(); QString commandLine; #ifdef Q_OS_WIN @@ -537,15 +545,16 @@ void TestRunnerDesktop::runInterfaceWithTestScript() { } void TestRunnerDesktop::interfaceExecutionComplete() { + QThread::msleep(500); QFileInfo testCompleted(QDir::toNativeSeparators(_snapshotFolder) +"/tests_completed.txt"); if (!testCompleted.exists()) { QMessageBox::critical(0, "Tests not completed", "Interface seems to have crashed before completion of the test scripts\nExisting images will be evaluated"); } + killProcesses(); + evaluateResults(); - killProcesses(); - // The High Fidelity AppData folder will be restored after evaluation has completed } @@ -591,7 +600,6 @@ void TestRunnerDesktop::addBuildNumberToResults(const QString& zippedFolderName) if (!QFile::rename(zippedFolderName, augmentedFilename)) { QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Could not rename '" + zippedFolderName + "' to '" + augmentedFilename); exit(-1); - } } @@ -667,6 +675,13 @@ void TestRunnerDesktop::checkTime() { QString TestRunnerDesktop::getPRNumberFromURL(const QString& url) { try { QStringList urlParts = url.split("/"); + if (urlParts.size() <= 2) { +#ifdef Q_OS_WIN + throw "URL not in expected format, should look like `https://deployment.highfidelity.com/jobs/pr-build/label%3Dwindows/13023/HighFidelity-Beta-Interface-PR14006-be76c43.exe`"; +#elif defined Q_OS_MAC + throw "URL not in expected format, should look like `https://deployment.highfidelity.com/jobs/pr-build/label%3Dwindows/13023/HighFidelity-Beta-Interface-PR14006-be76c43.dmg`"; +#endif + } QStringList filenameParts = urlParts[urlParts.size() - 1].split("-"); if (filenameParts.size() <= 3) { #ifdef Q_OS_WIN diff --git a/tools/nitpick/src/TestRunnerDesktop.h b/tools/nitpick/src/TestRunnerDesktop.h index 140a81f465..dce2dce2ba 100644 --- a/tools/nitpick/src/TestRunnerDesktop.h +++ b/tools/nitpick/src/TestRunnerDesktop.h @@ -12,7 +12,6 @@ #define hifi_testRunnerDesktop_h #include -#include #include #include #include @@ -32,8 +31,11 @@ public: std::vector timeEdits, QLabel* workingFolderLabel, QCheckBox* runServerless, + QCheckBox* usePreviousInstallationOnMobileCheckBox, QCheckBox* runLatest, QLineEdit* url, + QCheckBox* runFullSuite, + QLineEdit* scriptURL, QPushButton* runNow, QLabel* statusLabel, @@ -99,7 +101,6 @@ private: std::vector _dayCheckboxes; std::vector _timeEditCheckboxes; std::vector _timeEdits; - QLabel* _workingFolderLabel; QCheckBox* _runServerless; QPushButton* _runNow; QTimer* _timer; diff --git a/tools/nitpick/src/TestRunnerMobile.cpp b/tools/nitpick/src/TestRunnerMobile.cpp index ab276f3337..4d0d18ef3d 100644 --- a/tools/nitpick/src/TestRunnerMobile.cpp +++ b/tools/nitpick/src/TestRunnerMobile.cpp @@ -25,14 +25,16 @@ TestRunnerMobile::TestRunnerMobile( QPushButton* downloadAPKPushbutton, QPushButton* installAPKPushbutton, QPushButton* runInterfacePushbutton, + QCheckBox* usePreviousInstallationOnMobileCheckBox, QCheckBox* runLatest, QLineEdit* url, + QCheckBox* runFullSuite, + QLineEdit* scriptURL, QLabel* statusLabel, QObject* parent -) : QObject(parent), _adbInterface(NULL) +) : QObject(parent), TestRunner(workingFolderLabel, statusLabel, usePreviousInstallationOnMobileCheckBox, runLatest, url, runFullSuite, scriptURL) { - _workingFolderLabel = workingFolderLabel; _connectDeviceButton = connectDeviceButton; _pullFolderButton = pullFolderButton; _detectedDeviceLabel = detectedDeviceLabel; @@ -40,13 +42,15 @@ TestRunnerMobile::TestRunnerMobile( _downloadAPKPushbutton = downloadAPKPushbutton; _installAPKPushbutton = installAPKPushbutton; _runInterfacePushbutton = runInterfacePushbutton; - _runLatest = runLatest; - _url = url; - _statusLabel = statusLabel; folderLineEdit->setText("/sdcard/DCIM/TEST"); modelNames["SM_G955U1"] = "Samsung S8+ unlocked"; + modelNames["SM_N960U1"] = "Samsung Note 9 unlocked"; + modelNames["SM_T380"] = "Samsung Tab A"; + modelNames["Quest"] = "Quest"; + + _adbInterface = NULL; } TestRunnerMobile::~TestRunnerMobile() { @@ -66,6 +70,7 @@ void TestRunnerMobile::connectDevice() { QString devicesFullFilename{ _workingFolder + "/devices.txt" }; QString command = _adbInterface->getAdbCommand() + " devices -l > " + devicesFullFilename; + appendLog(command); system(command.toStdString().c_str()); if (!QFile::exists(devicesFullFilename)) { @@ -93,7 +98,7 @@ void TestRunnerMobile::connectDevice() { QString deviceID = tokens[0]; QString modelID = tokens[3].split(':')[1]; - QString modelName = "UKNOWN"; + QString modelName = "UNKNOWN"; if (modelNames.count(modelID) == 1) { modelName = modelNames[modelID]; } @@ -102,6 +107,8 @@ void TestRunnerMobile::connectDevice() { _pullFolderButton->setEnabled(true); _folderLineEdit->setEnabled(true); _downloadAPKPushbutton->setEnabled(true); + _installAPKPushbutton->setEnabled(true); + _runInterfacePushbutton->setEnabled(true); } } #endif @@ -109,6 +116,8 @@ void TestRunnerMobile::connectDevice() { void TestRunnerMobile::downloadAPK() { downloadBuildXml((void*)this); + + downloadComplete(); } @@ -141,11 +150,12 @@ void TestRunnerMobile::downloadComplete() { _statusLabel->setText("Downloading installer"); - nitpick->downloadFiles(urls, _workingFolder, filenames, (void*)this); + _downloader->downloadFiles(urls, _workingFolder, filenames, (void*)this); } else { _statusLabel->setText("Installer download complete"); - _installAPKPushbutton->setEnabled(true); } + + _installAPKPushbutton->setEnabled(true); } void TestRunnerMobile::installAPK() { @@ -154,11 +164,25 @@ void TestRunnerMobile::installAPK() { _adbInterface = new AdbInterface(); } + if (_installerFilename.isNull()) { + QString installerPathname = QFileDialog::getOpenFileName(nullptr, "Please select the APK", _workingFolder, + "Available APKs (*.apk)" + ); + + if (installerPathname.isNull()) { + return; + } + + // Remove the path + QStringList parts = installerPathname.split('/'); + _installerFilename = parts[parts.length() - 1]; + } + _statusLabel->setText("Installing"); QString command = _adbInterface->getAdbCommand() + " install -r -d " + _workingFolder + "/" + _installerFilename + " >" + _workingFolder + "/installOutput.txt"; + appendLog(command); system(command.toStdString().c_str()); _statusLabel->setText("Installation complete"); - _runInterfacePushbutton->setEnabled(true); #endif } @@ -169,7 +193,22 @@ void TestRunnerMobile::runInterface() { } _statusLabel->setText("Starting Interface"); - QString command = _adbInterface->getAdbCommand() + " shell monkey -p io.highfidelity.hifiinterface -v 1"; + + QString testScript = (_runFullSuite->isChecked()) + ? QString("https://raw.githubusercontent.com/") + nitpick->getSelectedUser() + "/hifi_tests/" + nitpick->getSelectedBranch() + "/tests/testRecursive.js" + : _scriptURL->text(); + + QString command = _adbInterface->getAdbCommand() + + " shell am start -n io.highfidelity.hifiinterface/.PermissionChecker" + + " --es args \\\"" + + " --url file:///~/serverless/tutorial.json" + + " --no-updater" + + " --no-login-suggestion" + + " --testScript " + testScript + " quitWhenFinished" + + " --testResultsLocation /sdcard/snapshots" + + "\\\""; + + appendLog(command); system(command.toStdString().c_str()); _statusLabel->setText("Interface started"); #endif @@ -182,7 +221,8 @@ void TestRunnerMobile::pullFolder() { } _statusLabel->setText("Pulling folder"); - QString command = _adbInterface->getAdbCommand() + " pull " + _folderLineEdit->text() + " " + _workingFolder + _installerFilename; + QString command = _adbInterface->getAdbCommand() + " pull " + _folderLineEdit->text() + " " + _workingFolder; + appendLog(command); system(command.toStdString().c_str()); _statusLabel->setText("Pull complete"); #endif diff --git a/tools/nitpick/src/TestRunnerMobile.h b/tools/nitpick/src/TestRunnerMobile.h index 52c2ba096d..f7b16da6f8 100644 --- a/tools/nitpick/src/TestRunnerMobile.h +++ b/tools/nitpick/src/TestRunnerMobile.h @@ -12,7 +12,6 @@ #define hifi_testRunnerMobile_h #include -#include #include #include @@ -31,8 +30,11 @@ public: QPushButton* downloadAPKPushbutton, QPushButton* installAPKPushbutton, QPushButton* runInterfacePushbutton, + QCheckBox* usePreviousInstallationOnMobileCheckBox, QCheckBox* runLatest, QLineEdit* url, + QCheckBox* runFullSuite, + QLineEdit* scriptURL, QLabel* statusLabel, QObject* parent = 0 diff --git a/tools/nitpick/ui/Nitpick.ui b/tools/nitpick/ui/Nitpick.ui index 47471522db..4a5a18f8d4 100644 --- a/tools/nitpick/ui/Nitpick.ui +++ b/tools/nitpick/ui/Nitpick.ui @@ -34,6 +34,9 @@ + + true + 45 @@ -495,7 +498,7 @@ - 20 + 240 70 120 20 @@ -549,13 +552,80 @@ - 170 + 175 100 - 451 + 445 21 + + + + 128 + 125 + 40 + 31 + + + + Script + + + + + false + + + + 175 + 130 + 445 + 21 + + + + + + + 20 + 130 + 120 + 20 + + + + <html><head/><body><p>If unchecked, will not show results during evaluation</p></body></html> + + + Run Full Suite + + + true + + + + + true + + + + 20 + 70 + 171 + 20 + + + + <html><head/><body><p>If unchecked, will not show results during evaluation</p></body></html> + + + usePreviousInstallation + + + false + + @@ -568,7 +638,7 @@ 10 - 90 + 150 160 30 @@ -581,7 +651,7 @@ 190 - 96 + 156 320 30 @@ -623,7 +693,7 @@ 460 - 410 + 440 160 30 @@ -639,7 +709,7 @@ 10 - 410 + 440 440 30 @@ -651,9 +721,9 @@ - 170 - 170 - 451 + 175 + 245 + 445 21 @@ -662,7 +732,7 @@ 20 - 170 + 245 120 20 @@ -684,7 +754,7 @@ 10 - 210 + 100 160 30 @@ -696,7 +766,7 @@ - 300 + 20 60 41 31 @@ -709,7 +779,7 @@ - 350 + 70 60 271 31 @@ -726,7 +796,7 @@ 10 - 250 + 325 160 30 @@ -742,7 +812,7 @@ 10 - 300 + 375 160 30 @@ -751,6 +821,86 @@ Run Interface + + + + 140 + 240 + 31 + 31 + + + + URL + + + + + false + + + + 175 + 275 + 445 + 21 + + + + + + + 140 + 270 + 40 + 31 + + + + Script + + + + + + 20 + 275 + 120 + 20 + + + + <html><head/><body><p>If unchecked, will not show results during evaluation</p></body></html> + + + Run Full Suite + + + true + + + + + true + + + + 20 + 210 + 171 + 20 + + + + <html><head/><body><p>If unchecked, will not show results during evaluation</p></body></html> + + + usePreviousInstallation + + + false + + @@ -921,6 +1071,9 @@ 21 + + true + groupBox From fc3b629cfc3c6e8601b664dbc6937dc410499a89 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Fri, 1 Mar 2019 14:02:18 -0800 Subject: [PATCH 12/44] New name. --- tools/nitpick/src/TestCreator.cpp | 1122 +++++++++++++++++++++++++++++ tools/nitpick/src/TestCreator.h | 170 +++++ 2 files changed, 1292 insertions(+) create mode 100644 tools/nitpick/src/TestCreator.cpp create mode 100644 tools/nitpick/src/TestCreator.h diff --git a/tools/nitpick/src/TestCreator.cpp b/tools/nitpick/src/TestCreator.cpp new file mode 100644 index 0000000000..cf4fe86162 --- /dev/null +++ b/tools/nitpick/src/TestCreator.cpp @@ -0,0 +1,1122 @@ +// +// TestCreator.cpp +// +// Created by Nissim Hadar on 2 Nov 2017. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "TestCreator.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "Nitpick.h" +extern Nitpick* nitpick; + +#include + +TestCreator::TestCreator(QProgressBar* progressBar, QCheckBox* checkBoxInteractiveMode) : _awsInterface(NULL) { + _downloader = new Downloader(); + + _progressBar = progressBar; + _checkBoxInteractiveMode = checkBoxInteractiveMode; + + _mismatchWindow.setModal(true); + + if (nitpick) { + nitpick->setUserText(GIT_HUB_DEFAULT_USER); + nitpick->setBranchText(GIT_HUB_DEFAULT_BRANCH); + } +} + +bool TestCreator::createTestResultsFolderPath(const QString& directory) { + QDateTime now = QDateTime::currentDateTime(); + _testResultsFolderPath = directory + "/" + TEST_RESULTS_FOLDER + "--" + now.toString(DATETIME_FORMAT) + "(local)[" + QHostInfo::localHostName() + "]"; + QDir testResultsFolder(_testResultsFolderPath); + + // Create a new test results folder + return QDir().mkdir(_testResultsFolderPath); +} + +QString TestCreator::zipAndDeleteTestResultsFolder() { + QString zippedResultsFileName { _testResultsFolderPath + ".zip" }; + QFileInfo fileInfo(zippedResultsFileName); + if (fileInfo.exists()) { + QFile::remove(zippedResultsFileName); + } + + QDir testResultsFolder(_testResultsFolderPath); + JlCompress::compressDir(_testResultsFolderPath + ".zip", _testResultsFolderPath); + + testResultsFolder.removeRecursively(); + + //In all cases, for the next evaluation + _testResultsFolderPath = ""; + _failureIndex = 1; + _successIndex = 1; + + return zippedResultsFileName; +} + +int TestCreator::compareImageLists() { + _progressBar->setMinimum(0); + _progressBar->setMaximum(_expectedImagesFullFilenames.length() - 1); + _progressBar->setValue(0); + _progressBar->setVisible(true); + + // Loop over both lists and compare each pair of images + // Quit loop if user has aborted due to a failed test. + bool keepOn{ true }; + int numberOfFailures{ 0 }; + for (int i = 0; keepOn && i < _expectedImagesFullFilenames.length(); ++i) { + // First check that images are the same size + QImage resultImage(_resultImagesFullFilenames[i]); + QImage expectedImage(_expectedImagesFullFilenames[i]); + + double similarityIndex; // in [-1.0 .. 1.0], where 1.0 means images are identical + + bool isInteractiveMode = (!_isRunningFromCommandLine && _checkBoxInteractiveMode->isChecked() && !_isRunningInAutomaticTestRun); + + // similarityIndex is set to -100.0 to indicate images are not the same size + if (isInteractiveMode && (resultImage.width() != expectedImage.width() || resultImage.height() != expectedImage.height())) { + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Images are not the same size"); + similarityIndex = -100.0; + } else { + similarityIndex = _imageComparer.compareImages(resultImage, expectedImage); + } + + TestResult testResult = TestResult{ + (float)similarityIndex, + _expectedImagesFullFilenames[i].left(_expectedImagesFullFilenames[i].lastIndexOf("/") + 1), // path to the test (including trailing /) + QFileInfo(_expectedImagesFullFilenames[i].toStdString().c_str()).fileName(), // filename of expected image + QFileInfo(_resultImagesFullFilenames[i].toStdString().c_str()).fileName() // filename of result image + }; + + _mismatchWindow.setTestResult(testResult); + + if (similarityIndex < THRESHOLD) { + ++numberOfFailures; + + if (!isInteractiveMode) { + appendTestResultsToFile(testResult, _mismatchWindow.getComparisonImage(), true); + } else { + _mismatchWindow.exec(); + + switch (_mismatchWindow.getUserResponse()) { + case USER_RESPONSE_PASS: + break; + case USE_RESPONSE_FAIL: + appendTestResultsToFile(testResult, _mismatchWindow.getComparisonImage(), true); + break; + case USER_RESPONSE_ABORT: + keepOn = false; + break; + default: + assert(false); + break; + } + } + } else { + appendTestResultsToFile(testResult, _mismatchWindow.getComparisonImage(), false); + } + + _progressBar->setValue(i); + } + + _progressBar->setVisible(false); + return numberOfFailures; +} + +int TestCreator::checkTextResults() { + // Create lists of failed and passed tests + QStringList nameFilterFailed; + nameFilterFailed << "*.failed.txt"; + QStringList testsFailed = QDir(_snapshotDirectory).entryList(nameFilterFailed, QDir::Files, QDir::Name); + + QStringList nameFilterPassed; + nameFilterPassed << "*.passed.txt"; + QStringList testsPassed = QDir(_snapshotDirectory).entryList(nameFilterPassed, QDir::Files, QDir::Name); + + // Add results to TestCreator Results folder + foreach(QString currentFilename, testsFailed) { + appendTestResultsToFile(currentFilename, true); + } + + foreach(QString currentFilename, testsPassed) { + appendTestResultsToFile(currentFilename, false); + } + + return testsFailed.length(); +} + +void TestCreator::appendTestResultsToFile(TestResult testResult, QPixmap comparisonImage, bool hasFailed) { + // Critical error if TestCreator Results folder does not exist + if (!QDir().exists(_testResultsFolderPath)) { + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Folder " + _testResultsFolderPath + " not found"); + exit(-1); + } + + // There are separate subfolders for failures and passes + QString resultFolderPath; + if (hasFailed) { + resultFolderPath = _testResultsFolderPath + "/Failure_" + QString::number(_failureIndex) + "--" + + testResult._actualImageFilename.left(testResult._actualImageFilename.length() - 4); + + ++_failureIndex; + } else { + resultFolderPath = _testResultsFolderPath + "/Success_" + QString::number(_successIndex) + "--" + + testResult._actualImageFilename.left(testResult._actualImageFilename.length() - 4); + + ++_successIndex; + } + + if (!QDir().mkdir(resultFolderPath)) { + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), + "Failed to create folder " + resultFolderPath); + exit(-1); + } + + QFile descriptionFile(resultFolderPath + "/" + TEST_RESULTS_FILENAME); + if (!descriptionFile.open(QIODevice::ReadWrite)) { + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to create file " + TEST_RESULTS_FILENAME); + exit(-1); + } + + // Create text file describing the failure + QTextStream stream(&descriptionFile); + stream << "TestCreator in folder " << testResult._pathname.left(testResult._pathname.length() - 1) << endl; // remove trailing '/' + stream << "Expected image was " << testResult._expectedImageFilename << endl; + stream << "Actual image was " << testResult._actualImageFilename << endl; + stream << "Similarity index was " << testResult._error << endl; + + descriptionFile.close(); + + // Copy expected and actual images, and save the difference image + QString sourceFile; + QString destinationFile; + + sourceFile = testResult._pathname + testResult._expectedImageFilename; + destinationFile = resultFolderPath + "/" + "Expected Image.png"; + if (!QFile::copy(sourceFile, destinationFile)) { + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to copy " + sourceFile + " to " + destinationFile); + exit(-1); + } + + sourceFile = testResult._pathname + testResult._actualImageFilename; + destinationFile = resultFolderPath + "/" + "Actual Image.png"; + if (!QFile::copy(sourceFile, destinationFile)) { + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to copy " + sourceFile + " to " + destinationFile); + exit(-1); + } + + comparisonImage.save(resultFolderPath + "/" + "Difference Image.png"); +} + +void::TestCreator::appendTestResultsToFile(QString testResultFilename, bool hasFailed) { + // The test name includes everything until the penultimate period + QString testNameTemp = testResultFilename.left(testResultFilename.lastIndexOf('.')); + QString testName = testResultFilename.left(testNameTemp.lastIndexOf('.')); + QString resultFolderPath; + if (hasFailed) { + resultFolderPath = _testResultsFolderPath + "/Failure_" + QString::number(_failureIndex) + "--" + testName; + ++_failureIndex; + } else { + resultFolderPath = _testResultsFolderPath + "/Success_" + QString::number(_successIndex) + "--" + testName; + ++_successIndex; + } + + if (!QDir().mkdir(resultFolderPath)) { + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), + "Failed to create folder " + resultFolderPath); + exit(-1); + } + + QString source = _snapshotDirectory + "/" + testResultFilename; + QString destination = resultFolderPath + "/Result.txt"; + if (!QFile::copy(source, destination)) { + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to copy " + testResultFilename + " to " + resultFolderPath); + exit(-1); + } +} + +void TestCreator::startTestsEvaluation(const bool isRunningFromCommandLine, + const bool isRunningInAutomaticTestRun, + const QString& snapshotDirectory, + const QString& branchFromCommandLine, + const QString& userFromCommandLine +) { + _isRunningFromCommandLine = isRunningFromCommandLine; + _isRunningInAutomaticTestRun = isRunningInAutomaticTestRun; + + if (snapshotDirectory.isNull()) { + // Get list of PNG images in folder, sorted by name + QString previousSelection = _snapshotDirectory; + QString parent = previousSelection.left(previousSelection.lastIndexOf('/')); + if (!parent.isNull() && parent.right(1) != "/") { + parent += "/"; + } + _snapshotDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder containing the snapshots", parent, + QFileDialog::ShowDirsOnly); + + // If user canceled then restore previous selection and return + if (_snapshotDirectory == "") { + _snapshotDirectory = previousSelection; + return; + } + } else { + _snapshotDirectory = snapshotDirectory; + _exitWhenComplete = (isRunningFromCommandLine && !isRunningInAutomaticTestRun); + } + + // Quit if test results folder could not be created + if (!createTestResultsFolderPath(_snapshotDirectory)) { + return; + } + + // Create two lists. The first is the test results, the second is the expected images + // The expected images are represented as a URL to enable download from GitHub + // Images that are in the wrong format are ignored. + + QStringList sortedTestResultsFilenames = createListOfAll_imagesInDirectory("png", _snapshotDirectory); + QStringList expectedImagesURLs; + + _resultImagesFullFilenames.clear(); + _expectedImagesFilenames.clear(); + _expectedImagesFullFilenames.clear(); + + QString branch = (branchFromCommandLine.isNull()) ? nitpick->getSelectedBranch() : branchFromCommandLine; + QString user = (userFromCommandLine.isNull()) ? nitpick->getSelectedUser() : userFromCommandLine; + + foreach(QString currentFilename, sortedTestResultsFilenames) { + QString fullCurrentFilename = _snapshotDirectory + "/" + currentFilename; + if (isInSnapshotFilenameFormat("png", currentFilename)) { + _resultImagesFullFilenames << fullCurrentFilename; + + QString expectedImagePartialSourceDirectory = getExpectedImagePartialSourceDirectory(currentFilename); + + // Images are stored on GitHub as ExpectedImage_ddddd.png + // Extract the digits at the end of the filename (excluding the file extension) + QString expectedImageFilenameTail = currentFilename.left(currentFilename.length() - 4).right(NUM_DIGITS); + QString expectedImageStoredFilename = EXPECTED_IMAGE_PREFIX + expectedImageFilenameTail + ".png"; + + QString imageURLString("https://raw.githubusercontent.com/" + user + "/" + GIT_HUB_REPOSITORY + "/" + branch + "/" + + expectedImagePartialSourceDirectory + "/" + expectedImageStoredFilename); + + expectedImagesURLs << imageURLString; + + // The image retrieved from GitHub needs a unique name + QString expectedImageFilename = currentFilename.replace("/", "_").replace(".png", "_EI.png"); + + _expectedImagesFilenames << expectedImageFilename; + _expectedImagesFullFilenames << _snapshotDirectory + "/" + expectedImageFilename; + } + } + + _downloader->downloadFiles(expectedImagesURLs, _snapshotDirectory, _expectedImagesFilenames, (void *)this); + finishTestsEvaluation(); +} + +void TestCreator::finishTestsEvaluation() { + // First - compare the pairs of images + int numberOfFailures = compareImageLists(); + + // Next - check text results + numberOfFailures += checkTextResults(); + + if (!_isRunningFromCommandLine && !_isRunningInAutomaticTestRun) { + if (numberOfFailures == 0) { + QMessageBox::information(0, "Success", "All images are as expected"); + } else { + QMessageBox::information(0, "Failure", "One or more images are not as expected"); + } + } + + QString zippedFolderName = zipAndDeleteTestResultsFolder(); + + if (_exitWhenComplete) { + exit(0); + } + + if (_isRunningInAutomaticTestRun) { + nitpick->automaticTestRunEvaluationComplete(zippedFolderName, numberOfFailures); + } +} + +bool TestCreator::isAValidDirectory(const QString& pathname) { + // Only process directories + QDir dir(pathname); + if (!dir.exists()) { + return false; + } + + // Ignore '.', '..' directories + if (pathname[pathname.length() - 1] == '.') { + return false; + } + + return true; +} + +QString TestCreator::extractPathFromTestsDown(const QString& fullPath) { + // `fullPath` includes the full path to the test. We need the portion below (and including) `tests` + QStringList pathParts = fullPath.split('/'); + int i{ 0 }; + while (i < pathParts.length() && pathParts[i] != "tests") { + ++i; + } + + if (i == pathParts.length()) { + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Bad testPathname"); + exit(-1); + } + + QString partialPath; + for (int j = i; j < pathParts.length(); ++j) { + partialPath += "/" + pathParts[j]; + } + + return partialPath; +} + +void TestCreator::includeTest(QTextStream& textStream, const QString& testPathname) { + QString partialPath = extractPathFromTestsDown(testPathname); + QString partialPathWithoutTests = partialPath.right(partialPath.length() - 7); + + textStream << "Script.include(testsRootPath + \"" << partialPathWithoutTests + "\");" << endl; +} + +void TestCreator::createTests(const QString& clientProfile) { + // Rename files sequentially, as ExpectedResult_00000.png, ExpectedResult_00001.png and so on + // Any existing expected result images will be deleted + QString previousSelection = _snapshotDirectory; + QString parent = previousSelection.left(previousSelection.lastIndexOf('/')); + if (!parent.isNull() && parent.right(1) != "/") { + parent += "/"; + } + + _snapshotDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder containing the snapshots", parent, + QFileDialog::ShowDirsOnly); + + // If user canceled then restore previous selection and return + if (_snapshotDirectory == "") { + _snapshotDirectory = previousSelection; + return; + } + + previousSelection = _testsRootDirectory; + parent = previousSelection.left(previousSelection.lastIndexOf('/')); + if (!parent.isNull() && parent.right(1) != "/") { + parent += "/"; + } + + _testsRootDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select test root folder", parent, + QFileDialog::ShowDirsOnly); + + // If user canceled then restore previous selection and return + if (_testsRootDirectory == "") { + _testsRootDirectory = previousSelection; + return; + } + + QStringList sortedImageFilenames = createListOfAll_imagesInDirectory("png", _snapshotDirectory); + + int i = 1; + const int maxImages = pow(10, NUM_DIGITS); + foreach (QString currentFilename, sortedImageFilenames) { + QString fullCurrentFilename = _snapshotDirectory + "/" + currentFilename; + if (isInSnapshotFilenameFormat("png", currentFilename)) { + if (i >= maxImages) { + QMessageBox::critical(0, "Error", "More than " + QString::number(maxImages) + " images not supported"); + exit(-1); + } + + // Path to test is extracted from the file name + // Example: + // filename is tests.engine.interaction.pointer.laser.distanceScaleEnd.00000.jpg + // path is <_testDirectory>/engine/interaction/pointer/laser/distanceScaleEnd + // + // Note: we don't use the first part and the last 2 parts of the filename at this stage + // + QStringList pathParts = currentFilename.split("."); + QString fullNewFileName = _testsRootDirectory; + for (int j = 1; j < pathParts.size() - 2; ++j) { + fullNewFileName += "/" + pathParts[j]; + } + + // The image _index is the penultimate component of the path parts (the last being the file extension) + QString newFilename = "ExpectedImage_" + pathParts[pathParts.size() - 2].rightJustified(5, '0') + ".png"; + fullNewFileName += "/" + newFilename; + + try { + if (QFile::exists(fullNewFileName)) { + QFile::remove(fullNewFileName); + } + QFile::copy(fullCurrentFilename, fullNewFileName); + } catch (...) { + QMessageBox::critical(0, "Error", "Could not copy file: " + fullCurrentFilename + " to " + fullNewFileName + "\n"); + exit(-1); + } + ++i; + } + } + + QMessageBox::information(0, "Success", "Test images have been created"); +} + +ExtractedText TestCreator::getTestScriptLines(QString testFileName) { + ExtractedText relevantTextFromTest; + + QFile inputFile(testFileName); + inputFile.open(QIODevice::ReadOnly); + if (!inputFile.isOpen()) { + QMessageBox::critical(0, + "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), + "Failed to open \"" + testFileName + ); + } + + QTextStream stream(&inputFile); + QString line = stream.readLine(); + + // Name of test is the string in the following line: + // nitpick.perform("Apply Material Entities to Avatars", Script.resolvePath("."), function(testType) {... + const QString ws("\\h*"); //white-space character + const QString functionPerformName(ws + "nitpick" + ws + "\\." + ws + "perform"); + const QString quotedString("\\\".+\\\""); + QString regexTestTitle(ws + functionPerformName + "\\(" + quotedString); + QRegularExpression lineContainingTitle = QRegularExpression(regexTestTitle); + + + // Each step is either of the following forms: + // nitpick.addStepSnapshot("Take snapshot"... + // nitpick.addStep("Clean up after test"... + const QString functionAddStepSnapshotName(ws + "nitpick" + ws + "\\." + ws + "addStepSnapshot"); + const QString regexStepSnapshot(ws + functionAddStepSnapshotName + ws + "\\(" + ws + quotedString + ".*"); + const QRegularExpression lineStepSnapshot = QRegularExpression(regexStepSnapshot); + + const QString functionAddStepName(ws + "nitpick" + ws + "\\." + ws + "addStep"); + const QString regexStep(ws + functionAddStepName + ws + "\\(" + ws + quotedString + ".*"); + const QRegularExpression lineStep = QRegularExpression(regexStep); + + while (!line.isNull()) { + line = stream.readLine(); + if (lineContainingTitle.match(line).hasMatch()) { + QStringList tokens = line.split('"'); + relevantTextFromTest.title = tokens[1]; + } else if (lineStepSnapshot.match(line).hasMatch()) { + QStringList tokens = line.split('"'); + QString nameOfStep = tokens[1]; + + Step *step = new Step(); + step->text = nameOfStep; + step->takeSnapshot = true; + relevantTextFromTest.stepList.emplace_back(step); + + } else if (lineStep.match(line).hasMatch()) { + QStringList tokens = line.split('"'); + QString nameOfStep = tokens[1]; + + Step *step = new Step(); + step->text = nameOfStep; + step->takeSnapshot = false; + relevantTextFromTest.stepList.emplace_back(step); + } + } + + inputFile.close(); + + return relevantTextFromTest; +} + +bool TestCreator::createFileSetup() { + // Folder selection + QString previousSelection = _testDirectory; + QString parent = previousSelection.left(previousSelection.lastIndexOf('/')); + if (!parent.isNull() && parent.right(1) != "/") { + parent += "/"; + } + + _testDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder containing the test", parent, + QFileDialog::ShowDirsOnly); + + // If user canceled then restore previous selection and return + if (_testDirectory == "") { + _testDirectory = previousSelection; + return false; + } + + return true; +} + +bool TestCreator::createAllFilesSetup() { + // Select folder to start recursing from + QString previousSelection = _testsRootDirectory; + QString parent = previousSelection.left(previousSelection.lastIndexOf('/')); + if (!parent.isNull() && parent.right(1) != "/") { + parent += "/"; + } + + _testsRootDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select the tests root folder", parent, + QFileDialog::ShowDirsOnly); + + // If user cancelled then restore previous selection and return + if (_testsRootDirectory == "") { + _testsRootDirectory = previousSelection; + return false; + } + + return true; +} + +// Create an MD file for a user-selected test. +// The folder selected must contain a script named "test.js", the file produced is named "test.md" +void TestCreator::createMDFile() { + if (!createFileSetup()) { + return; + } + + if (createMDFile(_testDirectory)) { + QMessageBox::information(0, "Success", "MD file has been created"); + } +} + +void TestCreator::createAllMDFiles() { + if (!createAllFilesSetup()) { + return; + } + + // First test if top-level folder has a test.js file + const QString testPathname{ _testsRootDirectory + "/" + TEST_FILENAME }; + QFileInfo fileInfo(testPathname); + if (fileInfo.exists()) { + createMDFile(_testsRootDirectory); + } + + QDirIterator it(_testsRootDirectory, QDirIterator::Subdirectories); + while (it.hasNext()) { + QString directory = it.next(); + + // Only process directories + QDir dir; + if (!isAValidDirectory(directory)) { + continue; + } + + const QString testPathname{ directory + "/" + TEST_FILENAME }; + QFileInfo fileInfo(testPathname); + if (fileInfo.exists()) { + createMDFile(directory); + } + } + + QMessageBox::information(0, "Success", "MD files have been created"); +} + +bool TestCreator::createMDFile(const QString& directory) { + // Verify folder contains test.js file + QString testFileName(directory + "/" + TEST_FILENAME); + QFileInfo testFileInfo(testFileName); + if (!testFileInfo.exists()) { + QMessageBox::critical(0, "Error", "Could not find file: " + TEST_FILENAME); + return false; + } + + ExtractedText testScriptLines = getTestScriptLines(testFileName); + + QString mdFilename(directory + "/" + "test.md"); + QFile mdFile(mdFilename); + if (!mdFile.open(QIODevice::WriteOnly)) { + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to create file " + mdFilename); + exit(-1); + } + + QTextStream stream(&mdFile); + + //TestCreator title + QString testName = testScriptLines.title; + stream << "# " << testName << "\n"; + + stream << "## Run this script URL: [Manual](./test.js?raw=true) [Auto](./testAuto.js?raw=true)(from menu/Edit/Open and Run scripts from URL...)." << "\n\n"; + + stream << "## Preconditions" << "\n"; + stream << "- In an empty region of a domain with editing rights." << "\n\n"; + + stream << "## Steps\n"; + stream << "Press '" + ADVANCE_KEY + "' key to advance step by step\n\n"; // note apostrophes surrounding 'ADVANCE_KEY' + + int snapShotIndex { 0 }; + for (size_t i = 0; i < testScriptLines.stepList.size(); ++i) { + stream << "### Step " << QString::number(i + 1) << "\n"; + stream << "- " << testScriptLines.stepList[i]->text << "\n"; + if ((i + 1 < testScriptLines.stepList.size()) && testScriptLines.stepList[i]->takeSnapshot) { + stream << "- ![](./ExpectedImage_" << QString::number(snapShotIndex).rightJustified(5, '0') << ".png)\n"; + ++snapShotIndex; + } + } + + mdFile.close(); + + foreach (auto test, testScriptLines.stepList) { + delete test; + } + testScriptLines.stepList.clear(); + + return true; +} + +void TestCreator::createTestAutoScript() { + if (!createFileSetup()) { + return; + } + + if (createTestAutoScript(_testDirectory)) { + QMessageBox::information(0, "Success", "'testAuto.js` script has been created"); + } +} + +void TestCreator::createAllTestAutoScripts() { + if (!createAllFilesSetup()) { + return; + } + + // First test if top-level folder has a test.js file + const QString testPathname{ _testsRootDirectory + "/" + TEST_FILENAME }; + QFileInfo fileInfo(testPathname); + if (fileInfo.exists()) { + createTestAutoScript(_testsRootDirectory); + } + + QDirIterator it(_testsRootDirectory, QDirIterator::Subdirectories); + while (it.hasNext()) { + QString directory = it.next(); + + // Only process directories + QDir dir; + if (!isAValidDirectory(directory)) { + continue; + } + + const QString testPathname{ directory + "/" + TEST_FILENAME }; + QFileInfo fileInfo(testPathname); + if (fileInfo.exists()) { + createTestAutoScript(directory); + } + } + + QMessageBox::information(0, "Success", "All 'testAuto.js' scripts have been created"); +} + +bool TestCreator::createTestAutoScript(const QString& directory) { + // Verify folder contains test.js file + QString testFileName(directory + "/" + TEST_FILENAME); + QFileInfo testFileInfo(testFileName); + if (!testFileInfo.exists()) { + QMessageBox::critical(0, "Error", "Could not find file: " + TEST_FILENAME); + return false; + } + + QString testAutoScriptFilename(directory + "/" + "testAuto.js"); + QFile testAutoScriptFile(testAutoScriptFilename); + if (!testAutoScriptFile.open(QIODevice::WriteOnly)) { + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), + "Failed to create file " + testAutoScriptFilename); + exit(-1); + } + + QTextStream stream(&testAutoScriptFile); + + stream << "if (typeof PATH_TO_THE_REPO_PATH_UTILS_FILE === 'undefined') PATH_TO_THE_REPO_PATH_UTILS_FILE = 'https://raw.githubusercontent.com/highfidelity/hifi_tests/master/tests/utils/branchUtils.js';\n"; + stream << "Script.include(PATH_TO_THE_REPO_PATH_UTILS_FILE);\n"; + stream << "var nitpick = createNitpick(Script.resolvePath('.'));\n\n"; + stream << "nitpick.enableAuto();\n\n"; + stream << "Script.include('./test.js?raw=true');\n"; + + testAutoScriptFile.close(); + return true; +} + +// Creates a single script in a user-selected folder. +// This script will run all text.js scripts in every applicable sub-folder +void TestCreator::createRecursiveScript() { + if (!createFileSetup()) { + return; + } + + createRecursiveScript(_testDirectory, true); + QMessageBox::information(0, "Success", "'testRecursive.js` script has been created"); +} + +// This method creates a `testRecursive.js` script in every sub-folder. +void TestCreator::createAllRecursiveScripts() { + if (!createAllFilesSetup()) { + return; + } + + createAllRecursiveScripts(_testsRootDirectory); + createRecursiveScript(_testsRootDirectory, false); + QMessageBox::information(0, "Success", "Scripts have been created"); +} + +void TestCreator::createAllRecursiveScripts(const QString& directory) { + QDirIterator it(directory, QDirIterator::Subdirectories); + + while (it.hasNext()) { + QString nextDirectory = it.next(); + if (isAValidDirectory(nextDirectory)) { + createAllRecursiveScripts(nextDirectory); + createRecursiveScript(nextDirectory, false); + } + } +} + +void TestCreator::createRecursiveScript(const QString& directory, bool interactiveMode) { + // If folder contains a test, then we are at a leaf + const QString testPathname{ directory + "/" + TEST_FILENAME }; + if (QFileInfo(testPathname).exists()) { + return; + } + + // Directories are included in reverse order. The nitpick scripts use a stack mechanism, + // so this ensures that the tests run in alphabetical order (a convenience when debugging) + QStringList directories; + QDirIterator it(directory); + while (it.hasNext()) { + QString subDirectory = it.next(); + + // Only process directories + if (!isAValidDirectory(subDirectory)) { + continue; + } + + const QString testPathname{ subDirectory + "/" + TEST_FILENAME }; + if (QFileInfo(testPathname).exists()) { + // Current folder contains a test script + directories.push_front(testPathname); + } + + const QString testRecursivePathname{ subDirectory + "/" + TEST_RECURSIVE_FILENAME }; + if (QFileInfo(testRecursivePathname).exists()) { + // Current folder contains a recursive script + directories.push_front(testRecursivePathname); + } + } + + // If 'directories' is empty, this means that this recursive script has no tests to call, so it is redundant + if (directories.length() == 0) { + return; + } + + // Open the recursive script file + const QString recursiveTestsFilename(directory + "/" + TEST_RECURSIVE_FILENAME); + QFile recursiveTestsFile(recursiveTestsFilename); + if (!recursiveTestsFile.open(QIODevice::WriteOnly | QIODevice::Text)) { + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), + "Failed to create \"" + TEST_RECURSIVE_FILENAME + "\" in directory \"" + directory + "\""); + + exit(-1); + } + + QTextStream textStream(&recursiveTestsFile); + + textStream << "// This is an automatically generated file, created by nitpick" << endl; + + // Include 'nitpick.js' + QString branch = nitpick->getSelectedBranch(); + QString user = nitpick->getSelectedUser(); + + textStream << "PATH_TO_THE_REPO_PATH_UTILS_FILE = \"https://raw.githubusercontent.com/" + user + "/hifi_tests/" + branch + + "/tests/utils/branchUtils.js\";" + << endl; + textStream << "Script.include(PATH_TO_THE_REPO_PATH_UTILS_FILE);" << endl << endl; + + // The 'depth' variable is used to signal when to start running the recursive scripts + textStream << "if (typeof depth === 'undefined') {" << endl; + textStream << " depth = 0;" << endl; + textStream << " nitpick = createNitpick(Script.resolvePath(\".\"));" << endl; + textStream << " testsRootPath = nitpick.getTestsRootPath();" << endl << endl; + textStream << " nitpick.enableRecursive();" << endl; + textStream << " nitpick.enableAuto();" << endl << endl; + textStream << " if (typeof Test !== 'undefined') {" << endl; + textStream << " Test.wait(10000);" << endl; + textStream << " }" << endl; + textStream << "} else {" << endl; + textStream << " depth++" << endl; + textStream << "}" << endl << endl; + + // Now include the test scripts + for (int i = 0; i < directories.length(); ++i) { + includeTest(textStream, directories.at(i)); + } + + textStream << endl; + textStream << "if (depth > 0) {" << endl; + textStream << " depth--;" << endl; + textStream << "} else {" << endl; + textStream << " nitpick.runRecursive();" << endl; + textStream << "}" << endl << endl; + + recursiveTestsFile.close(); +} + +void TestCreator::createTestsOutline() { + QString previousSelection = _testDirectory; + QString parent = previousSelection.left(previousSelection.lastIndexOf('/')); + if (!parent.isNull() && parent.right(1) != "/") { + parent += "/"; + } + + _testDirectory = + QFileDialog::getExistingDirectory(nullptr, "Please select the tests root folder", parent, QFileDialog::ShowDirsOnly); + + // If user canceled then restore previous selection and return + if (_testDirectory == "") { + _testDirectory = previousSelection; + return; + } + + const QString testsOutlineFilename { "testsOutline.md" }; + QString mdFilename(_testDirectory + "/" + testsOutlineFilename); + QFile mdFile(mdFilename); + if (!mdFile.open(QIODevice::WriteOnly)) { + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to create file " + mdFilename); + exit(-1); + } + + QTextStream stream(&mdFile); + + //TestCreator title + stream << "# Outline of all tests\n"; + stream << "Directories with an appended (*) have an automatic test\n\n"; + + // We need to know our current depth, as this isn't given by QDirIterator + int rootDepth { _testDirectory.count('/') }; + + // Each test is shown as the folder name linking to the matching GitHub URL, and the path to the associated test.md file + QDirIterator it(_testDirectory, QDirIterator::Subdirectories); + while (it.hasNext()) { + QString directory = it.next(); + + // Only process directories + if (!isAValidDirectory(directory)) { + continue; + } + + // Ignore the utils directory + if (directory.right(5) == "utils") { + continue; + } + + // The prefix is the MarkDown prefix needed for correct indentation + // It consists of 2 spaces for each level of indentation, folled by a dash sign + int currentDepth = directory.count('/') - rootDepth; + QString prefix = QString(" ").repeated(2 * currentDepth - 1) + " - "; + + // The directory name appears after the last slash (we are assured there is at least 1). + QString directoryName = directory.right(directory.length() - directory.lastIndexOf("/") - 1); + + // nitpick is run on a clone of the repository. We use relative paths, so we can use both local disk and GitHub + // For a test in "D:/GitHub/hifi_tests/tests/content/entity/zone/ambientLightInheritance" the + // GitHub URL is "./content/entity/zone/ambientLightInheritance?raw=true" + QString partialPath = directory.right(directory.length() - (directory.lastIndexOf("/tests/") + QString("/tests").length() + 1)); + QString url = "./" + partialPath; + + stream << prefix << "[" << directoryName << "](" << url << "?raw=true" << ")"; + + // note that md files may be named 'test.md' or 'testStory.md' + QFileInfo fileInfo1(directory + "/test.md"); + if (fileInfo1.exists()) { + stream << " [(test description)](" << url << "/test.md)"; + } + + QFileInfo fileInfo2(directory + "/testStory.md"); + if (fileInfo2.exists()) { + stream << " [(test description)](" << url << "/testStory.md)"; + } + + QFileInfo fileInfo3(directory + "/" + TEST_FILENAME); + if (fileInfo3.exists()) { + stream << " (*)"; + } + stream << "\n"; + } + + mdFile.close(); + + QMessageBox::information(0, "Success", "TestCreator outline file " + testsOutlineFilename + " has been created"); +} + +void TestCreator::createTestRailTestCases() { + QString previousSelection = _testDirectory; + QString parent = previousSelection.left(previousSelection.lastIndexOf('/')); + if (!parent.isNull() && parent.right(1) != "/") { + parent += "/"; + } + + _testDirectory = + QFileDialog::getExistingDirectory(nullptr, "Please select the tests root folder", parent, QFileDialog::ShowDirsOnly); + + // If user cancelled then restore previous selection and return + if (_testDirectory.isNull()) { + _testDirectory = previousSelection; + return; + } + + QString outputDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select a folder to store generated files in", + nullptr, QFileDialog::ShowDirsOnly); + + // If user cancelled then return + if (outputDirectory.isNull()) { + return; + } + + if (!_testRailInterface) { + _testRailInterface = new TestRailInterface; + } + + if (_testRailCreateMode == PYTHON) { + _testRailInterface->createTestSuitePython(_testDirectory, outputDirectory, nitpick->getSelectedUser(), + nitpick->getSelectedBranch()); + } else { + _testRailInterface->createTestSuiteXML(_testDirectory, outputDirectory, nitpick->getSelectedUser(), + nitpick->getSelectedBranch()); + } +} + +void TestCreator::createTestRailRun() { + QString outputDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select a folder to store generated files in", + nullptr, QFileDialog::ShowDirsOnly); + + if (outputDirectory.isNull()) { + return; + } + + + if (!_testRailInterface) { + _testRailInterface = new TestRailInterface; + } + + _testRailInterface->createTestRailRun(outputDirectory); +} + +void TestCreator::updateTestRailRunResult() { + QString testResults = QFileDialog::getOpenFileName(nullptr, "Please select the zipped test results to update from", nullptr, + "Zipped TestCreator Results (*.zip)"); + if (testResults.isNull()) { + return; + } + + QString tempDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select a folder to store temporary files in", + nullptr, QFileDialog::ShowDirsOnly); + if (tempDirectory.isNull()) { + return; + } + + + if (!_testRailInterface) { + _testRailInterface = new TestRailInterface; + } + + _testRailInterface->updateTestRailRunResults(testResults, tempDirectory); +} + +QStringList TestCreator::createListOfAll_imagesInDirectory(const QString& imageFormat, const QString& pathToImageDirectory) { + _imageDirectory = QDir(pathToImageDirectory); + QStringList nameFilters; + nameFilters << "*." + imageFormat; + + return _imageDirectory.entryList(nameFilters, QDir::Files, QDir::Name); +} + +// Snapshots are files in the following format: +// Filename (i.e. without extension) contains tests (this is based on all test scripts being within the tests folder) +// Last 5 characters in filename are digits (after removing the extension) +// Extension is 'imageFormat' +bool TestCreator::isInSnapshotFilenameFormat(const QString& imageFormat, const QString& filename) { + bool contains_tests = filename.contains("tests" + PATH_SEPARATOR); + + QString filenameWithoutExtension = filename.left(filename.lastIndexOf('.')); + bool last5CharactersAreDigits; + filenameWithoutExtension.right(5).toInt(&last5CharactersAreDigits, 10); + + bool extensionIsIMAGE_FORMAT = (filename.right(imageFormat.length()) == imageFormat); + + return (contains_tests && last5CharactersAreDigits && extensionIsIMAGE_FORMAT); +} + +// For a file named "D_GitHub_hifi-tests_tests_content_entity_zone_create_0.jpg", the test directory is +// D:/GitHub/hifi-tests/tests/content/entity/zone/create +// This method assumes the filename is in the correct format +QString TestCreator::getExpectedImageDestinationDirectory(const QString& filename) { + QString filenameWithoutExtension = filename.left(filename.length() - 4); + QStringList filenameParts = filenameWithoutExtension.split(PATH_SEPARATOR); + + QString result = filenameParts[0] + ":"; + + for (int i = 1; i < filenameParts.length() - 1; ++i) { + result += "/" + filenameParts[i]; + } + + return result; +} + +// For a file named "D_GitHub_hifi-tests_tests_content_entity_zone_create_0.jpg", the source directory on GitHub +// is ...tests/content/entity/zone/create +// This is used to create the full URL +// This method assumes the filename is in the correct format +QString TestCreator::getExpectedImagePartialSourceDirectory(const QString& filename) { + QString filenameWithoutExtension = filename.left(filename.length() - 4); + QStringList filenameParts = filenameWithoutExtension.split(PATH_SEPARATOR); + + // Note that the bottom-most "tests" folder is assumed to be the root + // This is required because the tests folder is named hifi_tests + int i { filenameParts.length() - 1 }; + while (i >= 0 && filenameParts[i] != "tests") { + --i; + } + + if (i < 0) { + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Bad filename"); + exit(-1); + } + + QString result = filenameParts[i]; + + for (int j = i + 1; j < filenameParts.length() - 1; ++j) { + result += "/" + filenameParts[j]; + } + + return result; +} + +void TestCreator::setTestRailCreateMode(TestRailCreateMode testRailCreateMode) { + _testRailCreateMode = testRailCreateMode; +} + +void TestCreator::createWebPage(QCheckBox* updateAWSCheckBox, QLineEdit* urlLineEdit) { + QString testResults = QFileDialog::getOpenFileName(nullptr, "Please select the zipped test results to update from", nullptr, + "Zipped TestCreator Results (TestResults--*.zip)"); + if (testResults.isNull()) { + return; + } + + QString workingDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select a folder to store temporary files in", + nullptr, QFileDialog::ShowDirsOnly); + if (workingDirectory.isNull()) { + return; + } + + if (!_awsInterface) { + _awsInterface = new AWSInterface; + } + + _awsInterface->createWebPageFromResults(testResults, workingDirectory, updateAWSCheckBox, urlLineEdit); +} \ No newline at end of file diff --git a/tools/nitpick/src/TestCreator.h b/tools/nitpick/src/TestCreator.h new file mode 100644 index 0000000000..59bbf7bbaf --- /dev/null +++ b/tools/nitpick/src/TestCreator.h @@ -0,0 +1,170 @@ +// +// TestCreator.h +// +// Created by Nissim Hadar on 2 Nov 2017. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_testCreator_h +#define hifi_testCreator_h + +#include +#include +#include +#include + +#include "AWSInterface.h" +#include "ImageComparer.h" +#include "Downloader.h" +#include "MismatchWindow.h" +#include "TestRailInterface.h" + +class Step { +public: + QString text; + bool takeSnapshot; +}; + +using StepList = std::vector; + +class ExtractedText { +public: + QString title; + StepList stepList; +}; + +enum TestRailCreateMode { + PYTHON, + XML +}; + +class TestCreator { +public: + TestCreator(QProgressBar* progressBar, QCheckBox* checkBoxInteractiveMode); + + void startTestsEvaluation(const bool isRunningFromCommandLine, + const bool isRunningInAutomaticTestRun, + const QString& snapshotDirectory = QString(), + const QString& branchFromCommandLine = QString(), + const QString& userFromCommandLine = QString()); + + void finishTestsEvaluation(); + + void createTests(const QString& clientProfile); + + void createTestsOutline(); + + bool createFileSetup(); + bool createAllFilesSetup(); + + void createMDFile(); + void createAllMDFiles(); + bool createMDFile(const QString& directory); + + void createTestAutoScript(); + void createAllTestAutoScripts(); + bool createTestAutoScript(const QString& directory); + + void createTestRailTestCases(); + void createTestRailRun(); + + void updateTestRailRunResult(); + + void createAllRecursiveScripts(); + void createAllRecursiveScripts(const QString& directory); + + void createRecursiveScript(); + void createRecursiveScript(const QString& directory, bool interactiveMode); + + int compareImageLists(); + int checkTextResults(); + + QStringList createListOfAll_imagesInDirectory(const QString& imageFormat, const QString& pathToImageDirectory); + + bool isInSnapshotFilenameFormat(const QString& imageFormat, const QString& filename); + + void includeTest(QTextStream& textStream, const QString& testPathname); + + void appendTestResultsToFile(TestResult testResult, QPixmap comparisonImage, bool hasFailed); + void appendTestResultsToFile(QString testResultFilename, bool hasFailed); + + bool createTestResultsFolderPath(const QString& directory); + QString zipAndDeleteTestResultsFolder(); + + static bool isAValidDirectory(const QString& pathname); + QString extractPathFromTestsDown(const QString& fullPath); + QString getExpectedImageDestinationDirectory(const QString& filename); + QString getExpectedImagePartialSourceDirectory(const QString& filename); + + ExtractedText getTestScriptLines(QString testFileName); + + void setTestRailCreateMode(TestRailCreateMode testRailCreateMode); + + void createWebPage(QCheckBox* updateAWSCheckBox, QLineEdit* urlLineEdit); + +private: + QProgressBar* _progressBar; + QCheckBox* _checkBoxInteractiveMode; + + bool _isRunningFromCommandLine{ false }; + bool _isRunningInAutomaticTestRun{ false }; + + const QString TEST_FILENAME{ "test.js" }; + const QString TEST_RECURSIVE_FILENAME{ "testRecursive.js" }; + const QString TEST_RESULTS_FOLDER { "TestResults" }; + const QString TEST_RESULTS_FILENAME { "TestResults.txt" }; + + const double THRESHOLD{ 0.965 }; + + QDir _imageDirectory; + + MismatchWindow _mismatchWindow; + + ImageComparer _imageComparer; + + QString _testResultsFolderPath; + int _failureIndex{ 1 }; + int _successIndex{ 1 }; + + // Expected images are in the format ExpectedImage_dddd.jpg (d == decimal digit) + const int NUM_DIGITS { 5 }; + const QString EXPECTED_IMAGE_PREFIX { "ExpectedImage_" }; + + // We have two directories to work with. + // The first is the directory containing the test we are working with + // The second is the root directory of all tests + // The third contains the snapshots taken for test runs that need to be evaluated + QString _testDirectory; + QString _testsRootDirectory; + QString _snapshotDirectory; + + QStringList _expectedImagesFilenames; + QStringList _expectedImagesFullFilenames; + QStringList _resultImagesFullFilenames; + + // Used for accessing GitHub + const QString GIT_HUB_DEFAULT_USER{ "highfidelity" }; + const QString GIT_HUB_DEFAULT_BRANCH{ "master" }; + const QString GIT_HUB_REPOSITORY{ "hifi_tests" }; + + const QString DATETIME_FORMAT{ "yyyy-MM-dd_hh-mm-ss" }; + + // NOTE: these need to match the appropriate var's in nitpick.js + // var advanceKey = "n"; + // var pathSeparator = "."; + const QString ADVANCE_KEY{ "n" }; + const QString PATH_SEPARATOR{ "." }; + + bool _exitWhenComplete{ false }; + + TestRailInterface* _testRailInterface; + TestRailCreateMode _testRailCreateMode { PYTHON }; + + AWSInterface* _awsInterface; + Downloader* _downloader; +}; + +#endif \ No newline at end of file From 695367a3e231954d1561ad0e792428eada0b7e70 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Fri, 1 Mar 2019 14:28:23 -0800 Subject: [PATCH 13/44] Updated for Mac. --- tools/nitpick/README.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/tools/nitpick/README.md b/tools/nitpick/README.md index 62e614c214..b4bcff81c8 100644 --- a/tools/nitpick/README.md +++ b/tools/nitpick/README.md @@ -67,10 +67,10 @@ These steps assume the hifi repository has been cloned to `~/hifi`. 1. Copy the downloaded file to (for example) **C:\adb** and extract in place. Verify you see *adb.exe* in **C:\adb\platform-tools\\**. 1. After installation - add the path to adb.exe to the Windows PATH environment variable (note that it is in *adb\platform-tools*). -1. `nitpick` is included in the High Fidelity installer but can also be downloaded from: +1. `nitpick` is included in the High Fidelity installer but can also be downloaded from (change X.X.X to correct version): [here]().* ### Mac -1. (first time) Install brew +1. (First time) Install brew In a terminal: `/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"` Note that you will need to press RETURN again, and will then be asked for your password. @@ -100,6 +100,16 @@ This is needed because the Mac Python supplied no longer links with the deprecat 1. Install the latest release of Boto3 via pip: pip3 install boto3 1. (First time)Install adb (the Android Debug Bridge) - in a terminal: `brew cask install android-platform-tools` +1. (First time) Set terminal privileges + 1. Click on Apple icon (top left) + 1. Select System Preferences... + 1. Select Security & Privacy + 1. Select Accessibility + 1. Click on "Click the lock to make changes" and enter passsword if requested + 1. Set Checkbox near *Terminal* to checked. + 1. Click on "Click the lock to prevent furthur changes" + 1. Close window + 1. `nitpick` is included in the High Fidelity installer but can also be downloaded from: [here]().* # Usage From a02693381966c82f7f875ce02774aaba71a3a621 Mon Sep 17 00:00:00 2001 From: danteruiz Date: Mon, 4 Mar 2019 10:56:14 -0800 Subject: [PATCH 14/44] keyboard handle scaling --- interface/src/ui/Keyboard.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/interface/src/ui/Keyboard.cpp b/interface/src/ui/Keyboard.cpp index d344e27d54..252d06bb6e 100644 --- a/interface/src/ui/Keyboard.cpp +++ b/interface/src/ui/Keyboard.cpp @@ -373,6 +373,12 @@ void Keyboard::raiseKeyboardAnchor(bool raise) const { void Keyboard::scaleKeyboard(float sensorToWorldScale) { auto entityScriptingInterface = DependencyManager::get(); + { + EntityItemProperties properties; + properties.setDimensions(_anchor.originalDimensions * sensorToWorldScale); + entityScriptingInterface->editEntity(_anchor.entityID, properties); + } + { EntityItemProperties properties; properties.setLocalPosition(_backPlate.localPosition * sensorToWorldScale); From 66125e1f0104e979fed5d248956ee6b01316c259 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 5 Mar 2019 10:21:49 -0800 Subject: [PATCH 15/44] Updated version. --- tools/nitpick/src/Nitpick.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/nitpick/src/Nitpick.cpp b/tools/nitpick/src/Nitpick.cpp index 03acd4a893..bf9b9c11ba 100644 --- a/tools/nitpick/src/Nitpick.cpp +++ b/tools/nitpick/src/Nitpick.cpp @@ -38,7 +38,7 @@ Nitpick::Nitpick(QWidget* parent) : QMainWindow(parent) { _ui.plainTextEdit->setReadOnly(true); - setWindowTitle("Nitpick - v3.1.0"); + setWindowTitle("Nitpick - v3.1.1"); clientProfiles << "VR-High" << "Desktop-High" << "Desktop-Low" << "Mobile-Touch" << "VR-Standalone"; _ui.clientProfileComboBox->insertItems(0, clientProfiles); From 8e9618d74064dd2ac043b84404cd4d74b2952c58 Mon Sep 17 00:00:00 2001 From: amantley Date: Tue, 5 Mar 2019 11:44:53 -0800 Subject: [PATCH 16/44] added a lower run animation to stop hovering when running --- .../resources/avatar/animations/run_fwd.fbx | Bin 1604368 -> 940272 bytes .../resources/avatar/avatar-animation.json | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/resources/avatar/animations/run_fwd.fbx b/interface/resources/avatar/animations/run_fwd.fbx index 2ea035e6941bfface831586837c6fd1e73b006d6..86add969e59d8c18d5bd6c40dbaa6ebe6eb739c3 100644 GIT binary patch literal 940272 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%0AluyZTKn^i;gerULk{~D9 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 b Date: Tue, 5 Mar 2019 14:24:38 -0800 Subject: [PATCH 17/44] add keyboard for html content --- interface/src/Application.cpp | 4 +++- interface/src/ui/Keyboard.cpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2c8d71af00..3d0012d807 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2342,6 +2342,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo } else { QObject::connect(webSurface.data(), &hifi::qml::OffscreenSurface::rootContextCreated, rootItemLoadedFunctor); } + auto surfaceContext = webSurface->getSurfaceContext(); + surfaceContext->setContextProperty("KeyboardScriptingInterface", DependencyManager::get().data()); } else { // FIXME: the tablet should use the OffscreenQmlSurfaceCache webSurface = QSharedPointer(new OffscreenQmlSurface(), [](OffscreenQmlSurface* webSurface) { @@ -3278,6 +3280,7 @@ void Application::setupQmlSurface(QQmlContext* surfaceContext, bool setAdditiona surfaceContext->setContextProperty("MyAvatar", DependencyManager::get()->getMyAvatar().get()); surfaceContext->setContextProperty("Entities", DependencyManager::get().data()); surfaceContext->setContextProperty("Snapshot", DependencyManager::get().data()); + surfaceContext->setContextProperty("KeyboardScriptingInterface", DependencyManager::get().data()); if (setAdditionalContextProperties) { auto tabletScriptingInterface = DependencyManager::get(); @@ -3288,7 +3291,6 @@ void Application::setupQmlSurface(QQmlContext* surfaceContext, bool setAdditiona surfaceContext->setContextProperty("Settings", SettingsScriptingInterface::getInstance()); surfaceContext->setContextProperty("MenuInterface", MenuScriptingInterface::getInstance()); - surfaceContext->setContextProperty("KeyboardScriptingInterface", DependencyManager::get().data()); surfaceContext->setContextProperty("Account", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED surfaceContext->setContextProperty("GlobalServices", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED diff --git a/interface/src/ui/Keyboard.cpp b/interface/src/ui/Keyboard.cpp index d344e27d54..80b0922a8c 100644 --- a/interface/src/ui/Keyboard.cpp +++ b/interface/src/ui/Keyboard.cpp @@ -65,7 +65,7 @@ static const glm::vec3 KEYBOARD_TABLET_OFFSET{0.30f, -0.38f, -0.04f}; static const glm::vec3 KEYBOARD_TABLET_DEGREES_OFFSET{-45.0f, 0.0f, 0.0f}; static const glm::vec3 KEYBOARD_TABLET_LANDSCAPE_OFFSET{-0.2f, -0.27f, -0.05f}; static const glm::vec3 KEYBOARD_TABLET_LANDSCAPE_DEGREES_OFFSET{-45.0f, 0.0f, -90.0f}; -static const glm::vec3 KEYBOARD_AVATAR_OFFSET{-0.6f, 0.3f, -0.7f}; +static const glm::vec3 KEYBOARD_AVATAR_OFFSET{-0.3f, 0.0f, -0.7f}; static const glm::vec3 KEYBOARD_AVATAR_DEGREES_OFFSET{0.0f, 180.0f, 0.0f}; static const QString SOUND_FILE = PathUtils::resourcesUrl() + "sounds/keyboardPress.mp3"; From 272ca5dc1c8f687df11bc36b59474afacf127306 Mon Sep 17 00:00:00 2001 From: danteruiz Date: Tue, 5 Mar 2019 16:23:40 -0800 Subject: [PATCH 18/44] disable entity scaling --- scripts/system/controllers/controllerModules/nearGrabEntity.js | 2 +- scripts/system/controllers/controllerScripts.js | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/system/controllers/controllerModules/nearGrabEntity.js b/scripts/system/controllers/controllerModules/nearGrabEntity.js index 0f8071677c..763c1a1ce0 100644 --- a/scripts/system/controllers/controllerModules/nearGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearGrabEntity.js @@ -134,7 +134,7 @@ Script.include("/~/system/libraries/controllers.js"); var scaleModuleName = this.hand === RIGHT_HAND ? "RightScaleEntity" : "LeftScaleEntity"; var scaleModule = getEnabledModuleByName(scaleModuleName); - if (scaleModule.grabbedThingID || scaleModule.isReady(controllerData).active) { + if (scaleModule && (scaleModule.grabbedThingID || scaleModule.isReady(controllerData).active)) { // we're rescaling -- don't start a grab. return makeRunningValues(false, [], []); } diff --git a/scripts/system/controllers/controllerScripts.js b/scripts/system/controllers/controllerScripts.js index 86ff7701c3..726e075fcc 100644 --- a/scripts/system/controllers/controllerScripts.js +++ b/scripts/system/controllers/controllerScripts.js @@ -30,7 +30,6 @@ var CONTOLLER_SCRIPTS = [ "controllerModules/teleport.js", "controllerModules/hudOverlayPointer.js", "controllerModules/mouseHMD.js", - "controllerModules/scaleEntity.js", "controllerModules/nearGrabHyperLinkEntity.js", "controllerModules/nearTabletHighlight.js", "controllerModules/nearGrabEntity.js", From 76609197e2387f2b5643f43afbb1416e9340f0be Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Tue, 5 Mar 2019 18:50:53 -0700 Subject: [PATCH 19/44] Read flow data from the fst file --- interface/src/avatar/MyAvatar.cpp | 32 +++++++++++++++++++ interface/src/avatar/MyAvatar.h | 1 + libraries/hfm/src/hfm/HFM.h | 9 ++++++ .../model-baker/src/model-baker/Baker.cpp | 9 ++++-- .../src/model-baker/ParseFlowDataTask.cpp | 26 +++++++++++++++ .../src/model-baker/ParseFlowDataTask.h | 24 ++++++++++++++ 6 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 libraries/model-baker/src/model-baker/ParseFlowDataTask.cpp create mode 100644 libraries/model-baker/src/model-baker/ParseFlowDataTask.h diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index af261f490b..ecc51132b9 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2337,6 +2337,7 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { _skeletonModel->setCauterizeBoneSet(_headBoneSet); _fstAnimGraphOverrideUrl = _skeletonModel->getGeometry()->getAnimGraphOverrideUrl(); initAnimGraph(); + initFlow(); _skeletonModelLoaded = true; } QObject::disconnect(*skeletonConnection); @@ -5383,6 +5384,37 @@ void MyAvatar::useFlow(bool isActive, bool isCollidable, const QVariantMap& phys } } +void MyAvatar::initFlow() { + auto &flowData = _skeletonModel->getHFMModel().flowData; + if (flowData._physicsData.size() > 0) { + QVariantMap physicsConfig; + QVariantMap collisionsConfig; + for (auto &data : flowData._physicsData) { + QJsonObject map = QJsonDocument::fromJson(data).object(); + if (!map.isEmpty() && map.keys().size() == 1) { + QString group = map.keys()[0]; + if (map[group].isObject()) { + physicsConfig.insert(group, map[group].toObject().toVariantMap()); + } + } + } + for (auto &data : flowData._collisionsData) { + QJsonObject map = QJsonDocument::fromJson(data).object(); + if (!map.isEmpty() && map.keys().size() == 1) { + QString jointName = map.keys()[0]; + if (map[jointName].isObject()) { + collisionsConfig.insert(jointName, map[jointName].toObject().toVariantMap()); + } + } + } + if (collisionsConfig.size() > 0) { + useFlow(true, true, physicsConfig, collisionsConfig); + } else { + useFlow(true, false, physicsConfig); + } + } +} + void MyAvatar::sendPacket(const QUuid& entityID, const EntityItemProperties& properties) const { auto treeRenderer = DependencyManager::get(); EntityTreePointer entityTree = treeRenderer ? treeRenderer->getTree() : nullptr; diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 2c8dedd430..c80412c949 100755 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -1751,6 +1751,7 @@ private: void updateCollisionSound(const glm::vec3& penetration, float deltaTime, float frequency); void initHeadBones(); void initAnimGraph(); + void initFlow(); // Avatar Preferences QUrl _fullAvatarURLFromPreferences; diff --git a/libraries/hfm/src/hfm/HFM.h b/libraries/hfm/src/hfm/HFM.h index 9f3de3302c..c2d8b14ba1 100644 --- a/libraries/hfm/src/hfm/HFM.h +++ b/libraries/hfm/src/hfm/HFM.h @@ -273,6 +273,13 @@ public: {} }; +class FlowData { +public: + FlowData() {}; + std::vector _physicsData; + std::vector _collisionsData; +}; + /// The runtime model format. class Model { public: @@ -319,6 +326,7 @@ public: QList blendshapeChannelNames; QMap jointRotationOffsets; + FlowData flowData; }; }; @@ -343,6 +351,7 @@ typedef hfm::Mesh HFMMesh; typedef hfm::AnimationFrame HFMAnimationFrame; typedef hfm::Light HFMLight; typedef hfm::Model HFMModel; +typedef hfm::FlowData FlowData; Q_DECLARE_METATYPE(HFMAnimationFrame) Q_DECLARE_METATYPE(QVector) diff --git a/libraries/model-baker/src/model-baker/Baker.cpp b/libraries/model-baker/src/model-baker/Baker.cpp index dfb18eef86..595f2ae0f7 100644 --- a/libraries/model-baker/src/model-baker/Baker.cpp +++ b/libraries/model-baker/src/model-baker/Baker.cpp @@ -20,6 +20,7 @@ #include "CalculateBlendshapeNormalsTask.h" #include "CalculateBlendshapeTangentsTask.h" #include "PrepareJointsTask.h" +#include "ParseFlowDataTask.h" namespace baker { @@ -101,7 +102,7 @@ namespace baker { class BuildModelTask { public: - using Input = VaryingSet5, std::vector, QMap, QHash>; + using Input = VaryingSet6, std::vector, QMap, QHash, FlowData>; using Output = hfm::Model::Pointer; using JobModel = Job::ModelIO; @@ -111,6 +112,7 @@ namespace baker { hfmModelOut->joints = QVector::fromStdVector(input.get2()); hfmModelOut->jointRotationOffsets = input.get3(); hfmModelOut->jointIndices = input.get4(); + hfmModelOut->flowData = input.get5(); output = hfmModelOut; } }; @@ -157,12 +159,15 @@ namespace baker { // Parse material mapping const auto materialMapping = model.addJob("ParseMaterialMapping", mapping); + // Parse flow data + const auto flowData = model.addJob("ParseFlowData", mapping); + // Combine the outputs into a new hfm::Model const auto buildBlendshapesInputs = BuildBlendshapesTask::Input(blendshapesPerMeshIn, normalsPerBlendshapePerMesh, tangentsPerBlendshapePerMesh).asVarying(); const auto blendshapesPerMeshOut = model.addJob("BuildBlendshapes", buildBlendshapesInputs); const auto buildMeshesInputs = BuildMeshesTask::Input(meshesIn, graphicsMeshes, normalsPerMesh, tangentsPerMesh, blendshapesPerMeshOut).asVarying(); const auto meshesOut = model.addJob("BuildMeshes", buildMeshesInputs); - const auto buildModelInputs = BuildModelTask::Input(hfmModelIn, meshesOut, jointsOut, jointRotationOffsets, jointIndices).asVarying(); + const auto buildModelInputs = BuildModelTask::Input(hfmModelIn, meshesOut, jointsOut, jointRotationOffsets, jointIndices, flowData).asVarying(); const auto hfmModelOut = model.addJob("BuildModel", buildModelInputs); output = Output(hfmModelOut, materialMapping); diff --git a/libraries/model-baker/src/model-baker/ParseFlowDataTask.cpp b/libraries/model-baker/src/model-baker/ParseFlowDataTask.cpp new file mode 100644 index 0000000000..1a298b3d4b --- /dev/null +++ b/libraries/model-baker/src/model-baker/ParseFlowDataTask.cpp @@ -0,0 +1,26 @@ +// +// Created by Luis Cuenca on 5/3/2019 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "ParseFlowDataTask.h" + +void ParseFlowDataTask::run(const baker::BakeContextPointer& context, const Input& mapping, Output& output) { + FlowData flowData; + static const QString FLOW_PHYSICS_FIELD = "flowPhysicsData"; + static const QString FLOW_COLLISIONS_FIELD = "flowCollisionsData"; + for (auto &mappingIter = mapping.begin(); mappingIter != mapping.end(); mappingIter++) { + if (mappingIter.key() == FLOW_PHYSICS_FIELD || mappingIter.key() == FLOW_COLLISIONS_FIELD) { + QByteArray flowDataValue = mappingIter.value().toByteArray(); + if (mappingIter.key() == FLOW_PHYSICS_FIELD) { + flowData._physicsData.push_back(flowDataValue); + } else { + flowData._collisionsData.push_back(flowDataValue); + } + } + } + output = flowData; +} diff --git a/libraries/model-baker/src/model-baker/ParseFlowDataTask.h b/libraries/model-baker/src/model-baker/ParseFlowDataTask.h new file mode 100644 index 0000000000..3c85430165 --- /dev/null +++ b/libraries/model-baker/src/model-baker/ParseFlowDataTask.h @@ -0,0 +1,24 @@ +// +// Created by Luis Cuenca on 3/7/2019 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_ParseFlowDataTask_h +#define hifi_ParseFlowDataTask_h + +#include +#include "Engine.h" + +class ParseFlowDataTask { +public: + using Input = QVariantHash; + using Output = FlowData; + using JobModel = baker::Job::ModelIO; + + void run(const baker::BakeContextPointer& context, const Input& input, Output& output); +}; + +#endif // hifi_ParseFlowDataTask_h From beeeb74f17ea740b4bf573a66c86b7e7ddee76d9 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Tue, 5 Mar 2019 18:56:02 -0700 Subject: [PATCH 20/44] Fix creation date --- libraries/model-baker/src/model-baker/ParseFlowDataTask.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/model-baker/src/model-baker/ParseFlowDataTask.h b/libraries/model-baker/src/model-baker/ParseFlowDataTask.h index 3c85430165..7e1bc9fba1 100644 --- a/libraries/model-baker/src/model-baker/ParseFlowDataTask.h +++ b/libraries/model-baker/src/model-baker/ParseFlowDataTask.h @@ -1,5 +1,5 @@ // -// Created by Luis Cuenca on 3/7/2019 +// Created by Luis Cuenca on 5/3/2019 // Copyright 2019 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. From dfb434ea09d3eb479117023355551daa6b8cb6ca Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Wed, 6 Mar 2019 09:25:49 -0700 Subject: [PATCH 21/44] Fix warning and refactoring --- interface/src/avatar/MyAvatar.cpp | 65 +++++++------------ interface/src/avatar/MyAvatar.h | 2 +- libraries/hfm/src/hfm/HFM.h | 6 +- .../src/model-baker/ParseFlowDataTask.cpp | 19 ++++-- 4 files changed, 40 insertions(+), 52 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index ecc51132b9..578c1915fd 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2323,24 +2323,25 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { std::shared_ptr skeletonConnection = std::make_shared(); *skeletonConnection = QObject::connect(_skeletonModel.get(), &SkeletonModel::skeletonLoaded, [this, skeletonModelChangeCount, skeletonConnection]() { - if (skeletonModelChangeCount == _skeletonModelChangeCount) { + if (skeletonModelChangeCount == _skeletonModelChangeCount) { - if (_fullAvatarModelName.isEmpty()) { - // Store the FST file name into preferences - const auto& mapping = _skeletonModel->getGeometry()->getMapping(); - if (mapping.value("name").isValid()) { - _fullAvatarModelName = mapping.value("name").toString(); - } - } + if (_fullAvatarModelName.isEmpty()) { + // Store the FST file name into preferences + const auto& mapping = _skeletonModel->getGeometry()->getMapping(); + if (mapping.value("name").isValid()) { + _fullAvatarModelName = mapping.value("name").toString(); + } + } - initHeadBones(); - _skeletonModel->setCauterizeBoneSet(_headBoneSet); - _fstAnimGraphOverrideUrl = _skeletonModel->getGeometry()->getAnimGraphOverrideUrl(); - initAnimGraph(); - initFlow(); - _skeletonModelLoaded = true; - } - QObject::disconnect(*skeletonConnection); + initHeadBones(); + _skeletonModel->setCauterizeBoneSet(_headBoneSet); + _fstAnimGraphOverrideUrl = _skeletonModel->getGeometry()->getAnimGraphOverrideUrl(); + initAnimGraph(); + initFlowFromFST(); + + _skeletonModelLoaded = true; + } + QObject::disconnect(*skeletonConnection); }); saveAvatarUrl(); @@ -5384,33 +5385,11 @@ void MyAvatar::useFlow(bool isActive, bool isCollidable, const QVariantMap& phys } } -void MyAvatar::initFlow() { - auto &flowData = _skeletonModel->getHFMModel().flowData; - if (flowData._physicsData.size() > 0) { - QVariantMap physicsConfig; - QVariantMap collisionsConfig; - for (auto &data : flowData._physicsData) { - QJsonObject map = QJsonDocument::fromJson(data).object(); - if (!map.isEmpty() && map.keys().size() == 1) { - QString group = map.keys()[0]; - if (map[group].isObject()) { - physicsConfig.insert(group, map[group].toObject().toVariantMap()); - } - } - } - for (auto &data : flowData._collisionsData) { - QJsonObject map = QJsonDocument::fromJson(data).object(); - if (!map.isEmpty() && map.keys().size() == 1) { - QString jointName = map.keys()[0]; - if (map[jointName].isObject()) { - collisionsConfig.insert(jointName, map[jointName].toObject().toVariantMap()); - } - } - } - if (collisionsConfig.size() > 0) { - useFlow(true, true, physicsConfig, collisionsConfig); - } else { - useFlow(true, false, physicsConfig); +void MyAvatar::initFlowFromFST() { + if (_skeletonModel->isLoaded()) { + auto &flowData = _skeletonModel->getHFMModel().flowData; + if (flowData.shouldInitFlow()) { + useFlow(true, flowData.shouldInitCollisions(), flowData._physicsConfig, flowData._collisionsConfig); } } } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index c80412c949..46189c4a11 100755 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -1751,7 +1751,7 @@ private: void updateCollisionSound(const glm::vec3& penetration, float deltaTime, float frequency); void initHeadBones(); void initAnimGraph(); - void initFlow(); + void initFlowFromFST(); // Avatar Preferences QUrl _fullAvatarURLFromPreferences; diff --git a/libraries/hfm/src/hfm/HFM.h b/libraries/hfm/src/hfm/HFM.h index c2d8b14ba1..4f44595eaa 100644 --- a/libraries/hfm/src/hfm/HFM.h +++ b/libraries/hfm/src/hfm/HFM.h @@ -276,8 +276,10 @@ public: class FlowData { public: FlowData() {}; - std::vector _physicsData; - std::vector _collisionsData; + QVariantMap _physicsConfig; + QVariantMap _collisionsConfig; + bool shouldInitFlow() const { return _physicsConfig.size() > 0; } + bool shouldInitCollisions() const { return _collisionsConfig.size() > 0; } }; /// The runtime model format. diff --git a/libraries/model-baker/src/model-baker/ParseFlowDataTask.cpp b/libraries/model-baker/src/model-baker/ParseFlowDataTask.cpp index 1a298b3d4b..6dff4f8c55 100644 --- a/libraries/model-baker/src/model-baker/ParseFlowDataTask.cpp +++ b/libraries/model-baker/src/model-baker/ParseFlowDataTask.cpp @@ -12,13 +12,20 @@ void ParseFlowDataTask::run(const baker::BakeContextPointer& context, const Inpu FlowData flowData; static const QString FLOW_PHYSICS_FIELD = "flowPhysicsData"; static const QString FLOW_COLLISIONS_FIELD = "flowCollisionsData"; - for (auto &mappingIter = mapping.begin(); mappingIter != mapping.end(); mappingIter++) { + for (auto mappingIter = mapping.begin(); mappingIter != mapping.end(); mappingIter++) { if (mappingIter.key() == FLOW_PHYSICS_FIELD || mappingIter.key() == FLOW_COLLISIONS_FIELD) { - QByteArray flowDataValue = mappingIter.value().toByteArray(); - if (mappingIter.key() == FLOW_PHYSICS_FIELD) { - flowData._physicsData.push_back(flowDataValue); - } else { - flowData._collisionsData.push_back(flowDataValue); + QByteArray data = mappingIter.value().toByteArray(); + QJsonObject dataObject = QJsonDocument::fromJson(data).object(); + if (!dataObject.isEmpty() && dataObject.keys().size() == 1) { + QString key = dataObject.keys()[0]; + if (dataObject[key].isObject()) { + QVariantMap dataMap = dataObject[key].toObject().toVariantMap(); + if (mappingIter.key() == FLOW_PHYSICS_FIELD) { + flowData._physicsConfig.insert(key, dataMap); + } else { + flowData._collisionsConfig.insert(key, dataMap); + } + } } } } From d4cea6009f5018d6bb33a486822d2c9a2927f697 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 6 Mar 2019 10:45:13 -0800 Subject: [PATCH 22/44] Add the version code to the Quest android build --- android/apps/interface/build.gradle | 5 ----- android/apps/questInterface/build.gradle | 3 +-- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/android/apps/interface/build.gradle b/android/apps/interface/build.gradle index f954fbc1f4..bb2745ca22 100644 --- a/android/apps/interface/build.gradle +++ b/android/apps/interface/build.gradle @@ -36,11 +36,6 @@ apply plugin: 'com.android.application' android { compileSdkVersion 26 - //buildToolsVersion '27.0.3' - - def appVersionCode = Integer.valueOf(VERSION_CODE ?: 1) - def appVersionName = RELEASE_NUMBER ?: "1.0" - defaultConfig { applicationId "io.highfidelity.hifiinterface" minSdkVersion 24 diff --git a/android/apps/questInterface/build.gradle b/android/apps/questInterface/build.gradle index 6f4f6b7441..c54401a81b 100644 --- a/android/apps/questInterface/build.gradle +++ b/android/apps/questInterface/build.gradle @@ -18,12 +18,11 @@ task renameHifiACTaskRelease(type: Copy) { android { compileSdkVersion 28 - defaultConfig { applicationId "io.highfidelity.questInterface" minSdkVersion 24 targetSdkVersion 28 - versionCode 1 + versionCode appVersionCode versionName appVersionName ndk { abiFilters 'arm64-v8a' } externalNativeBuild { From f5afc2033feed8c932f5715005ea2c8370c1765a Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 28 Feb 2019 15:10:55 -0800 Subject: [PATCH 23/44] work through stocking vs update issues, and cleanup --- .../qml/hifi/commerce/checkout/Checkout.qml | 41 ++++++++----------- .../hifi/commerce/marketplace/Marketplace.qml | 3 +- .../commerce/marketplace/MarketplaceItem.qml | 19 ++++----- .../hifi/commerce/purchases/PurchasedItem.qml | 2 +- .../qml/hifi/commerce/wallet/Wallet.qml | 4 -- 5 files changed, 27 insertions(+), 42 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml index 9589c842e6..93ca366d37 100644 --- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml @@ -41,8 +41,8 @@ Rectangle { property string itemAuthor; property int itemEdition: -1; property bool hasSomethingToTradeIn: alreadyOwned && (itemEdition > 0); // i.e., don't trade in your artist's proof - property bool isTradingIn: isUpdating && hasSomethingToTradeIn; - property bool isStocking: availability === 'not for sale' && creator === Account.username; + property bool isTradingIn: canUpdate && hasSomethingToTradeIn; + property bool isStocking: (availability === 'not for sale') && (creator === Account.username) && ; property string certificateId; property double balanceAfterPurchase; property bool alreadyOwned: false; // Including proofs @@ -59,7 +59,7 @@ Rectangle { property bool canRezCertifiedItems: Entities.canRezCertified() || Entities.canRezTmpCertified(); property string referrer; property bool isInstalled; - property bool isUpdating; + property bool canUpdate; property string availability: "available"; property string creator: ""; property string baseAppURL; @@ -144,6 +144,7 @@ Rectangle { } onAvailableUpdatesResult: { + // Answers the updatable original item cert data still owned by this user that are EITHER instances of this marketplace id, or update to this marketplace id. if (result.status !== 'success') { console.log("Failed to get Available Updates", result.data.message); } else { @@ -155,7 +156,7 @@ Rectangle { if (root.itemEdition !== -1 && root.itemEdition !== parseInt(result.data.updates[i].edition_number)) { continue; } - root.isUpdating = true; + root.canUpdate = true; root.baseItemName = result.data.updates[i].base_item_title; // This CertID is the one corresponding to the base item CertID that the user already owns root.certificateId = result.data.updates[i].certificate_id; @@ -166,7 +167,7 @@ Rectangle { } } - if (result.data.updates.length === 0 || root.isUpdating) { + if (result.data.updates.length === 0 || root.canUpdate) { root.availableUpdatesReceived = true; refreshBuyUI(); } else { @@ -266,13 +267,6 @@ Rectangle { } } } - MouseArea { - enabled: titleBarContainer.usernameDropdownVisible; - anchors.fill: parent; - onClicked: { - titleBarContainer.usernameDropdownVisible = false; - } - } // // TITLE BAR END // @@ -481,7 +475,7 @@ Rectangle { FiraSansSemiBold { id: itemPriceText; text: isTradingIn ? "FREE\nUPDATE" : - (isStocking ? "Free for creator" : + (isStocking ? "Free for creator" : ((root.itemPrice === -1) ? "--" : ((root.itemPrice > 0) ? root.itemPrice : "FREE"))); // Text size size: isTradingIn ? 20 : 26; @@ -580,7 +574,7 @@ Rectangle { // "View in Inventory" button HifiControlsUit.Button { id: viewInMyPurchasesButton; - visible: isCertified && dataReady && (isUpdating ? !hasSomethingToTradeIn : alreadyOwned); + visible: isCertified && dataReady && (isTradingIn ? hasSomethingToTradeIn : alreadyOwned); color: hifi.buttons.blue; colorScheme: hifi.colorSchemes.light; anchors.top: buyTextContainer.visible ? buyTextContainer.bottom : checkoutActionButtonsContainer.top; @@ -588,9 +582,9 @@ Rectangle { height: 50; anchors.left: parent.left; anchors.right: parent.right; - text: root.isUpdating ? "UPDATE TO THIS ITEM FOR FREE" : "VIEW THIS ITEM IN YOUR INVENTORY"; + text: (canUpdate && !isTradingIn) ? "UPDATE TO THIS ITEM FOR FREE" : "VIEW THIS ITEM IN YOUR INVENTORY"; onClicked: { - if (root.isUpdating) { + if (root.canUpdate) { sendToScript({method: 'checkout_goToPurchases', filterText: root.baseItemName}); } else { sendToScript({method: 'checkout_goToPurchases', filterText: root.itemName}); @@ -602,7 +596,11 @@ Rectangle { HifiControlsUit.Button { id: buyButton; visible: isTradingIn || !alreadyOwned || isStocking || !(root.itemType === "avatar" || root.itemType === "app"); - enabled: (root.balanceAfterPurchase >= 0 && dataReady) || (!root.isCertified) || root.isUpdating; + property bool checkBalance: dataReady && (root.availability === "available") + enabled: (checkBalance && (balanceAfterPurchase >= 0)) || !isCertified || isTradingIn || isStocking; + text: isTradingIn ? "Confirm Update" : + (enabled ? (viewInMyPurchasesButton.visible ? "Get It Again" : (dataReady ? "Get Item" : "--")) : + (checkBalance ? "Insufficient Funds" : availability)) color: viewInMyPurchasesButton.visible ? hifi.buttons.white : hifi.buttons.blue; colorScheme: hifi.colorSchemes.light; anchors.top: viewInMyPurchasesButton.visible ? viewInMyPurchasesButton.bottom : @@ -611,13 +609,6 @@ Rectangle { height: 50; anchors.left: parent.left; anchors.right: parent.right; - text: isTradingIn ? - "CONFIRM UPDATE" : - (((root.isCertified) ? - (dataReady ? - ((viewInMyPurchasesButton.visible && !root.isUpdating) ? "Get It Again" : "Confirm") : - "--") : - "Get Item")); onClicked: { if (isTradingIn) { // If we're updating an app, the existing app needs to be uninstalled. @@ -1209,7 +1200,7 @@ Rectangle { buyText.text = ""; // If the user IS on the checkout page for the updated version of an owned item... - if (root.isUpdating) { + if (root.canUpdate) { // If the user HAS already selected a specific edition to update... if (hasSomethingToTradeIn) { buyText.text = "By pressing \"Confirm Update\", you agree to trade in your old item for the updated item that replaces it."; diff --git a/interface/resources/qml/hifi/commerce/marketplace/Marketplace.qml b/interface/resources/qml/hifi/commerce/marketplace/Marketplace.qml index ca6838efea..a8b769703d 100644 --- a/interface/resources/qml/hifi/commerce/marketplace/Marketplace.qml +++ b/interface/resources/qml/hifi/commerce/marketplace/Marketplace.qml @@ -112,7 +112,7 @@ Rectangle { marketplaceItem.image_url = result.data.thumbnail_url; marketplaceItem.name = result.data.title; marketplaceItem.likes = result.data.likes; - if(result.data.has_liked !== undefined) { + if (result.data.has_liked !== undefined) { marketplaceItem.liked = result.data.has_liked; } marketplaceItem.creator = result.data.creator; @@ -122,6 +122,7 @@ Rectangle { marketplaceItem.attributions = result.data.attributions; marketplaceItem.license = result.data.license; marketplaceItem.availability = result.data.availability; + marketplaceItem.updated_item_id = result.updated_item_id; marketplaceItem.created_at = result.data.created_at; marketplaceItemScrollView.contentHeight = marketplaceItemContent.height; itemsList.visible = false; diff --git a/interface/resources/qml/hifi/commerce/marketplace/MarketplaceItem.qml b/interface/resources/qml/hifi/commerce/marketplace/MarketplaceItem.qml index 97e5c10a6b..e909d27e2b 100644 --- a/interface/resources/qml/hifi/commerce/marketplace/MarketplaceItem.qml +++ b/interface/resources/qml/hifi/commerce/marketplace/MarketplaceItem.qml @@ -2,7 +2,7 @@ // MarketplaceListItem.qml // qml/hifi/commerce/marketplace // -// MarketplaceListItem +// MarketplaceItem // // Created by Roxanne Skelly on 2019-01-22 // Copyright 2019 High Fidelity, Inc. @@ -34,6 +34,7 @@ Rectangle { property var categories: [] property int price: 0 property string availability: "unknown" + property string updated_item_id: "" property var attributions: [] property string description: "" property string license: "" @@ -42,7 +43,6 @@ Rectangle { property bool isLoggedIn: false; property int edition: -1; property bool supports3DHTML: false; - onCategoriesChanged: { categoriesListModel.clear(); @@ -264,15 +264,12 @@ Rectangle { } height: 50 - property bool isNFS: availability === "not for sale" // Note: server will say "sold out" or "invalidated" before it says NFS - property bool isMine: creator === Account.username - property bool isUpgrade: root.edition >= 0 - property int costToMe: ((isMine && isNFS) || isUpgrade) ? 0 : price - property bool isAvailable: costToMe >= 0 - - text: isUpgrade ? "UPGRADE FOR FREE" : (isAvailable ? (costToMe || "FREE") : availability) - enabled: isAvailable - buttonGlyph: isAvailable ? (costToMe ? hifi.glyphs.hfc : "") : "" + property bool isUpdate: root.edition >= 0 // Special case of updating from a specific older item + property bool isStocking: (creator === Account.username) && (availability === "not for sale") && !updated_item_id // Note: server will say "sold out" or "invalidated" before it says NFS + property bool isFreeSpecial: isStocking || isUpdate + enabled: isFreeSpecial || (availability === 'available') + buttonGlyph: (enabled && !isUpdate && (price > 0)) ? hifi.glyphs.hfc : "" + text: isUpdate ? "UPDATE FOR FREE" : (isStocking ? "FREE STOCK" : (enabled ? (price || "FREE") : availability)) color: hifi.buttons.blue onClicked: root.buy(); diff --git a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml index df6e216b32..2c2fed1d8f 100644 --- a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml +++ b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml @@ -380,7 +380,7 @@ Item { if (updateButton.visible && uninstallButton.visible) { item.itemButtonText = ""; item.glyphSize = 20; - } else { + } else if (item) { item.itemButtonText = "Send to Trash"; item.glyphSize = 30; } diff --git a/interface/resources/qml/hifi/commerce/wallet/Wallet.qml b/interface/resources/qml/hifi/commerce/wallet/Wallet.qml index f8e2c9115b..ea74549084 100644 --- a/interface/resources/qml/hifi/commerce/wallet/Wallet.qml +++ b/interface/resources/qml/hifi/commerce/wallet/Wallet.qml @@ -40,10 +40,6 @@ Rectangle { source: "images/wallet-bg.jpg"; } - Component.onDestruction: { - KeyboardScriptingInterface.raised = false; - } - Connections { target: Commerce; From 416cde4c1f4e3efbe80c8d83d77bb3c6e55c82b1 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 28 Feb 2019 17:31:35 -0800 Subject: [PATCH 24/44] fix uses of updated_item_id that got lost --- interface/resources/qml/hifi/commerce/checkout/Checkout.qml | 4 +++- .../resources/qml/hifi/commerce/marketplace/Marketplace.qml | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml index 93ca366d37..60114e3db9 100644 --- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml @@ -42,7 +42,7 @@ Rectangle { property int itemEdition: -1; property bool hasSomethingToTradeIn: alreadyOwned && (itemEdition > 0); // i.e., don't trade in your artist's proof property bool isTradingIn: canUpdate && hasSomethingToTradeIn; - property bool isStocking: (availability === 'not for sale') && (creator === Account.username) && ; + property bool isStocking: (availability === 'not for sale') && (creator === Account.username) && !updated_item_id; property string certificateId; property double balanceAfterPurchase; property bool alreadyOwned: false; // Including proofs @@ -61,6 +61,7 @@ Rectangle { property bool isInstalled; property bool canUpdate; property string availability: "available"; + property string updated_item_id: ""; property string creator: ""; property string baseAppURL; property int currentUpdatesPage: 1; @@ -1101,6 +1102,7 @@ Rectangle { root.itemAuthor = result.data.creator; root.itemType = result.data.item_type || "unknown"; root.availability = result.data.availability; + root.updated_item_id = result.data.updated_item_id || "" root.creator = result.data.creator; if (root.itemType === "unknown") { root.itemHref = result.data.review_url; diff --git a/interface/resources/qml/hifi/commerce/marketplace/Marketplace.qml b/interface/resources/qml/hifi/commerce/marketplace/Marketplace.qml index a8b769703d..6e089843dc 100644 --- a/interface/resources/qml/hifi/commerce/marketplace/Marketplace.qml +++ b/interface/resources/qml/hifi/commerce/marketplace/Marketplace.qml @@ -122,7 +122,7 @@ Rectangle { marketplaceItem.attributions = result.data.attributions; marketplaceItem.license = result.data.license; marketplaceItem.availability = result.data.availability; - marketplaceItem.updated_item_id = result.updated_item_id; + marketplaceItem.updated_item_id = result.data.updated_item_id || ""; marketplaceItem.created_at = result.data.created_at; marketplaceItemScrollView.contentHeight = marketplaceItemContent.height; itemsList.visible = false; From 366dd935dda30aba1e44a168bdde7bf018cbeeac Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Fri, 1 Mar 2019 12:32:03 -0800 Subject: [PATCH 25/44] trading in has nothing to do with whether you own the new item --- interface/resources/qml/hifi/commerce/checkout/Checkout.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml index 60114e3db9..c2bf745527 100644 --- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml @@ -40,7 +40,7 @@ Rectangle { property string itemHref; property string itemAuthor; property int itemEdition: -1; - property bool hasSomethingToTradeIn: alreadyOwned && (itemEdition > 0); // i.e., don't trade in your artist's proof + property bool hasSomethingToTradeIn: itemEdition > 0; // i.e., don't trade in your artist's proof property bool isTradingIn: canUpdate && hasSomethingToTradeIn; property bool isStocking: (availability === 'not for sale') && (creator === Account.username) && !updated_item_id; property string certificateId; From ddfd437696e09de4bfab64bf15e0488c8c91b06a Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Tue, 5 Mar 2019 14:50:06 -0800 Subject: [PATCH 26/44] ensure error message when marketplace update fails --- interface/resources/qml/hifi/commerce/checkout/Checkout.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml index c2bf745527..3ace6f381f 100644 --- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml @@ -180,7 +180,7 @@ Rectangle { onUpdateItemResult: { if (result.status !== 'success') { - failureErrorText.text = result.message; + failureErrorText.text = result.data ? (result.data.message || "Unknown Error") : JSON.stringify(result); root.activeView = "checkoutFailure"; } else { root.itemHref = result.data.download_url; From 0dbc83049b71f1207e2dfe30a8e4096cfd0ab656 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Wed, 6 Mar 2019 13:28:14 -0800 Subject: [PATCH 27/44] Make AnimPose from mat4 work better for matrices with negative determinants. Took part of this code from glm::decompose() which references https://opensource.apple.com/source/WebCore/WebCore-514/platform/graphics/transforms/TransformationMatrix.cpp --- libraries/animation/src/AnimPose.cpp | 50 +++++++++++++++++++++++ libraries/animation/src/AnimTwoBoneIK.cpp | 6 +-- tests/animation/CMakeLists.txt | 2 +- 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/libraries/animation/src/AnimPose.cpp b/libraries/animation/src/AnimPose.cpp index d77514e691..8b030fac39 100644 --- a/libraries/animation/src/AnimPose.cpp +++ b/libraries/animation/src/AnimPose.cpp @@ -13,12 +13,16 @@ #include #include #include "AnimUtil.h" +#include const AnimPose AnimPose::identity = AnimPose(glm::vec3(1.0f), glm::quat(), glm::vec3(0.0f)); +#define NEW_VERSION + AnimPose::AnimPose(const glm::mat4& mat) { +#if defined(ORIGINAL_VERSION) static const float EPSILON = 0.0001f; _scale = extractScale(mat); // quat_cast doesn't work so well with scaled matrices, so cancel it out. @@ -30,6 +34,52 @@ AnimPose::AnimPose(const glm::mat4& mat) { _rot = glm::quat(_rot.w * oneOverLength, _rot.x * oneOverLength, _rot.y * oneOverLength, _rot.z * oneOverLength); } _trans = extractTranslation(mat); +#elif defined(DECOMPOSE_VERSION) + // glm::decompose code + glm::vec3 scale; + glm::quat rotation; + glm::vec3 translation; + glm::vec3 skew; + glm::vec4 perspective; + bool result = glm::decompose(mat, scale, rotation, translation, skew, perspective); + _scale = scale; + _rot = rotation; + _trans = translation; + if (!result) { + // hack + const float HACK_FACTOR = 1000.0f; + glm::mat4 tmp = glm::scale(mat, HACK_FACTOR); + glm::decompose(tmp, scale, rotation, translation, skew, perspective); + _scale = scale / HACK_FACTOR; + _rot = rotation; + _trans = translation; + } +#elif defined(NEW_VERSION) + glm::mat3 m(mat); + _scale = glm::vec3(glm::length(m[0]), glm::length(m[1]), glm::length(m[2])); + float det = glm::determinant(m); + + glm::mat3 tmp; + if (det < 0.0f) { + _scale *= -1.0f; + } + + // quat_cast doesn't work so well with scaled matrices, so cancel out scale. + // also, as a side effect, multiply mirrored matrices by -1 to get the right rotation out. + tmp[0] = m[0] * (1.0f / _scale[0]); + tmp[1] = m[1] * (1.0f / _scale[1]); + tmp[2] = m[2] * (1.0f / _scale[2]); + _rot = glm::quat_cast(tmp); + + // normalize quat if necessary + float lengthSquared = glm::length2(_rot); + if (glm::abs(lengthSquared - 1.0f) > EPSILON) { + float oneOverLength = 1.0f / sqrtf(lengthSquared); + _rot = glm::quat(_rot.w * oneOverLength, _rot.x * oneOverLength, _rot.y * oneOverLength, _rot.z * oneOverLength); + } + + _trans = extractTranslation(mat); +#endif } glm::vec3 AnimPose::operator*(const glm::vec3& rhs) const { diff --git a/libraries/animation/src/AnimTwoBoneIK.cpp b/libraries/animation/src/AnimTwoBoneIK.cpp index 8960b15940..c91518d5db 100644 --- a/libraries/animation/src/AnimTwoBoneIK.cpp +++ b/libraries/animation/src/AnimTwoBoneIK.cpp @@ -156,7 +156,7 @@ const AnimPoseVec& AnimTwoBoneIK::evaluate(const AnimVariantMap& animVars, const glm::quat relMidRot = glm::angleAxis(midAngle, _midHingeAxis); // insert new relative pose into the chain and rebuild it. - ikChain.setRelativePoseAtJointIndex(_midJointIndex, AnimPose(relMidRot, underPoses[_midJointIndex].trans())); + ikChain.setRelativePoseAtJointIndex(_midJointIndex, AnimPose(underPoses[_midJointIndex].scale(), relMidRot, underPoses[_midJointIndex].trans())); ikChain.buildDirtyAbsolutePoses(); // recompute tip pose after mid joint has been rotated @@ -180,7 +180,7 @@ const AnimPoseVec& AnimTwoBoneIK::evaluate(const AnimVariantMap& animVars, const // transform result back into parent relative frame. glm::quat relBaseRot = glm::inverse(baseParentPose.rot()) * absRot; - ikChain.setRelativePoseAtJointIndex(_baseJointIndex, AnimPose(relBaseRot, underPoses[_baseJointIndex].trans())); + ikChain.setRelativePoseAtJointIndex(_baseJointIndex, AnimPose(underPoses[_baseJointIndex].scale(), relBaseRot, underPoses[_baseJointIndex].trans())); } // recompute midJoint pose after base has been rotated. @@ -189,7 +189,7 @@ const AnimPoseVec& AnimTwoBoneIK::evaluate(const AnimVariantMap& animVars, const // transform target rotation in to parent relative frame. glm::quat relTipRot = glm::inverse(midJointPose.rot()) * targetPose.rot(); - ikChain.setRelativePoseAtJointIndex(_tipJointIndex, AnimPose(relTipRot, underPoses[_tipJointIndex].trans())); + ikChain.setRelativePoseAtJointIndex(_tipJointIndex, AnimPose(underPoses[_tipJointIndex].scale(), relTipRot, underPoses[_tipJointIndex].trans())); // blend with the underChain ikChain.blend(underChain, alpha); diff --git a/tests/animation/CMakeLists.txt b/tests/animation/CMakeLists.txt index 2af4d5f2cd..e378750425 100644 --- a/tests/animation/CMakeLists.txt +++ b/tests/animation/CMakeLists.txt @@ -1,7 +1,7 @@ # Declare dependencies macro (setup_testcase_dependencies) # link in the shared libraries - link_hifi_libraries(shared animation gpu fbx hfm graphics networking test-utils) + link_hifi_libraries(shared animation gpu fbx hfm graphics networking test-utils image) package_libraries_for_deployment() endmacro () From c6b2697b44532e1fd06789ca08c6484f6dfd2eb3 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Wed, 6 Mar 2019 13:28:55 -0800 Subject: [PATCH 28/44] cleanup --- .../resources/qml/hifi/commerce/marketplace/Marketplace.qml | 1 - .../qml/hifi/commerce/marketplace/MarketplaceItem.qml | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/marketplace/Marketplace.qml b/interface/resources/qml/hifi/commerce/marketplace/Marketplace.qml index 6e089843dc..3004af6c15 100644 --- a/interface/resources/qml/hifi/commerce/marketplace/Marketplace.qml +++ b/interface/resources/qml/hifi/commerce/marketplace/Marketplace.qml @@ -980,7 +980,6 @@ Rectangle { xhr.open("GET", url); xhr.onreadystatechange = function() { if (xhr.readyState == XMLHttpRequest.DONE) { - console.log(xhr.responseText); licenseText.text = xhr.responseText; licenseInfo.visible = true; } diff --git a/interface/resources/qml/hifi/commerce/marketplace/MarketplaceItem.qml b/interface/resources/qml/hifi/commerce/marketplace/MarketplaceItem.qml index e909d27e2b..8c9d3c31c8 100644 --- a/interface/resources/qml/hifi/commerce/marketplace/MarketplaceItem.qml +++ b/interface/resources/qml/hifi/commerce/marketplace/MarketplaceItem.qml @@ -52,7 +52,7 @@ Rectangle { } onDescriptionChanged: { - + if(root.supports3DHTML) { descriptionTextModel.clear(); descriptionTextModel.append({text: description}); @@ -271,7 +271,7 @@ Rectangle { buttonGlyph: (enabled && !isUpdate && (price > 0)) ? hifi.glyphs.hfc : "" text: isUpdate ? "UPDATE FOR FREE" : (isStocking ? "FREE STOCK" : (enabled ? (price || "FREE") : availability)) color: hifi.buttons.blue - + onClicked: root.buy(); } From d063825269485e8ea09e937fd6e39dd2a17c41ca Mon Sep 17 00:00:00 2001 From: David Back Date: Wed, 6 Mar 2019 12:17:19 -0800 Subject: [PATCH 29/44] export unity material data to materialMap in fst --- .../Assets/Editor/AvatarExporter.cs | 430 +++++++++++++----- tools/unity-avatar-exporter/Assets/README.txt | 2 +- .../avatarExporter.unitypackage | Bin 13667 -> 15949 bytes 3 files changed, 317 insertions(+), 115 deletions(-) diff --git a/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter.cs b/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter.cs index 7b90145223..40994c8f46 100644 --- a/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter.cs +++ b/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter.cs @@ -14,12 +14,14 @@ using System.Collections.Generic; class AvatarExporter : MonoBehaviour { // update version number for every PR that changes this file, also set updated version in README file - static readonly string AVATAR_EXPORTER_VERSION = "0.2"; + static readonly string AVATAR_EXPORTER_VERSION = "0.3.1"; static readonly float HIPS_GROUND_MIN_Y = 0.01f; static readonly float HIPS_SPINE_CHEST_MIN_SEPARATION = 0.001f; static readonly int MAXIMUM_USER_BONE_COUNT = 256; static readonly string EMPTY_WARNING_TEXT = "None"; + static readonly string TEXTURES_DIRECTORY = "textures"; + static readonly string DEFAULT_MATERIAL_NAME = "No Name"; // TODO: use regex static readonly string[] RECOMMENDED_UNITY_VERSIONS = new string[] { @@ -195,8 +197,17 @@ class AvatarExporter : MonoBehaviour { " Thumb Intermediate", " Thumb Proximal", }; + + static readonly string STANDARD_SHADER = "Standard"; + static readonly string STANDARD_ROUGHNESS_SHADER = "Standard (Roughness setup)"; + static readonly string STANDARD_SPECULAR_SHADER = "Standard (Specular setup)"; + static readonly string[] SUPPORTED_SHADERS = new string[] { + STANDARD_SHADER, + STANDARD_ROUGHNESS_SHADER, + STANDARD_SPECULAR_SHADER, + }; - enum BoneRule { + enum AvatarRule { RecommendedUnityVersion, SingleRoot, NoDuplicateMapping, @@ -215,14 +226,14 @@ class AvatarExporter : MonoBehaviour { HipsNotOnGround, HipsSpineChestNotCoincident, TotalBoneCountUnderLimit, - BoneRuleEnd, + AvatarRuleEnd, }; // rules that are treated as errors and prevent exporting, otherwise rules will show as warnings - static readonly BoneRule[] EXPORT_BLOCKING_BONE_RULES = new BoneRule[] { - BoneRule.HipsMapped, - BoneRule.SpineMapped, - BoneRule.ChestMapped, - BoneRule.HeadMapped, + static readonly AvatarRule[] EXPORT_BLOCKING_AVATAR_RULES = new AvatarRule[] { + AvatarRule.HipsMapped, + AvatarRule.SpineMapped, + AvatarRule.ChestMapped, + AvatarRule.HeadMapped, }; class UserBoneInformation { @@ -255,15 +266,67 @@ class AvatarExporter : MonoBehaviour { } } - static Dictionary userBoneInfos = new Dictionary(); - static Dictionary humanoidToUserBoneMappings = new Dictionary(); - static BoneTreeNode userBoneTree = new BoneTreeNode(); - static Dictionary failedBoneRules = new Dictionary(); + class MaterialData { + public Color albedo; + public string albedoMap; + public double metallic; + public string metallicMap; + public double roughness; + public string roughnessMap; + public string normalMap; + public string heightMap; + public string occlusionMap; + public Color emissive; + public string emissiveMap; + + public string getJSON() { + string json = "{ \"materialVersion\": 1, \"materials\": { "; + json += "\"albedo\": [" + albedo.r + ", " + albedo.g + ", " + albedo.b + "], "; + if (!string.IsNullOrEmpty(albedoMap)) { + json += "\"albedoMap\": \"" + albedoMap + "\", "; + } + json += "\"metallic\": " + metallic + ", "; + if (!string.IsNullOrEmpty(metallicMap)) { + json += "\"metallicMap\": \"" + metallicMap + "\", "; + } + json += "\"roughness\": " + roughness + ", "; + if (!string.IsNullOrEmpty(roughnessMap)) { + json += "\"roughnessMap\": \"" + roughnessMap + "\", "; + } + if (!string.IsNullOrEmpty(normalMap)) { + json += "\"normalMap\": \"" + normalMap + "\", "; + } + if (!string.IsNullOrEmpty(heightMap)) { + json += "\"heightMap\": \"" + heightMap + "\", "; + } + if (!string.IsNullOrEmpty(occlusionMap)) { + json += "\"occlusionMap\": \"" + occlusionMap + "\", "; + } + json += "\"emissive\": [" + emissive.r + ", " + emissive.g + ", " + emissive.b + "] "; + if (!string.IsNullOrEmpty(emissiveMap)) { + json += "\", emissiveMap\": \"" + emissiveMap + "\""; + } + json += "} }"; + return json; + } + } static string assetPath = ""; static string assetName = ""; + + static ModelImporter modelImporter; static HumanDescription humanDescription; - static Dictionary dependencyTextures = new Dictionary(); + static Dictionary userBoneInfos = new Dictionary(); + static Dictionary humanoidToUserBoneMappings = new Dictionary(); + static BoneTreeNode userBoneTree = new BoneTreeNode(); + static Dictionary failedAvatarRules = new Dictionary(); + + static Dictionary textureDependencies = new Dictionary(); + static Dictionary materialMappings = new Dictionary(); + static Dictionary materialDatas = new Dictionary(); + static List materialAlternateStandardShader = new List(); + static Dictionary materialUnsupportedShader = new Dictionary(); + static List normalMapAndHeightMapNotBoth = new List(); [MenuItem("High Fidelity/Export New Avatar")] static void ExportNewAvatar() { @@ -280,7 +343,10 @@ class AvatarExporter : MonoBehaviour { EditorUtility.DisplayDialog("About", "High Fidelity, Inc.\nAvatar Exporter\nVersion " + AVATAR_EXPORTER_VERSION, "Ok"); } - static void ExportSelectedAvatar(bool updateAvatar) { + static void ExportSelectedAvatar(bool updateAvatar) { + // ensure everything is saved to file before exporting + AssetDatabase.SaveAssets(); + string[] guids = Selection.assetGUIDs; if (guids.Length != 1) { if (guids.Length == 0) { @@ -292,7 +358,7 @@ class AvatarExporter : MonoBehaviour { } assetPath = AssetDatabase.GUIDToAssetPath(Selection.assetGUIDs[0]); assetName = Path.GetFileNameWithoutExtension(assetPath); - ModelImporter modelImporter = ModelImporter.GetAtPath(assetPath) as ModelImporter; + modelImporter = ModelImporter.GetAtPath(assetPath) as ModelImporter; if (Path.GetExtension(assetPath).ToLower() != ".fbx" || modelImporter == null) { EditorUtility.DisplayDialog("Error", "Please select an .fbx model asset to export.", "Ok"); return; @@ -302,26 +368,37 @@ class AvatarExporter : MonoBehaviour { " the Rig section of it's Inspector window.", "Ok"); return; } - + humanDescription = modelImporter.humanDescription; - SetUserBoneInformation(); string textureWarnings = SetTextureDependencies(); + SetBoneAndMaterialInformation(); // check if we should be substituting a bone for a missing UpperChest mapping AdjustUpperChestMapping(); - // format resulting bone rule failure strings - // consider export-blocking bone rules to be errors and show them in an error dialog, - // and also include any other bone rule failures plus texture warnings as warnings in the dialog + // format resulting avatar rule failure strings + // consider export-blocking avatar rules to be errors and show them in an error dialog, + // and also include any other avatar rule failures plus texture warnings as warnings in the dialog string boneErrors = ""; string warnings = ""; - foreach (var failedBoneRule in failedBoneRules) { - if (Array.IndexOf(EXPORT_BLOCKING_BONE_RULES, failedBoneRule.Key) >= 0) { - boneErrors += failedBoneRule.Value + "\n\n"; + foreach (var failedAvatarRule in failedAvatarRules) { + if (Array.IndexOf(EXPORT_BLOCKING_AVATAR_RULES, failedAvatarRule.Key) >= 0) { + boneErrors += failedAvatarRule.Value + "\n\n"; } else { - warnings += failedBoneRule.Value + "\n\n"; + warnings += failedAvatarRule.Value + "\n\n"; } } + foreach (string materialName in materialAlternateStandardShader) { + warnings += "The material " + materialName + " is not using the recommended variation of the Standard shader. " + + "We recommend you change it to Standard (Roughness setup) shader for improved performance.\n\n"; + } + foreach (var material in materialUnsupportedShader) { + warnings += "The material " + material.Key + " is using an unsupported shader " + material.Value + + ". Please change it to a Standard shader type.\n\n"; + } + foreach (string materialName in normalMapAndHeightMapNotBoth) { + warnings += "The material " + materialName + " has both a normal map and a height map assigned but can only use 1.\n\n"; + } warnings += textureWarnings; if (!string.IsNullOrEmpty(boneErrors)) { // if there are both errors and warnings then warnings will be displayed with errors in the error dialog @@ -408,9 +485,9 @@ class AvatarExporter : MonoBehaviour { modelImporter.SaveAndReimport(); // redo parent names, joint mappings, and user bone positions due to the fbx change - // as well as re-check the bone rules for failures + // as well as re-check the avatar rules for failures humanDescription = modelImporter.humanDescription; - SetUserBoneInformation(); + SetBoneAndMaterialInformation(); } } } else { @@ -456,7 +533,7 @@ class AvatarExporter : MonoBehaviour { return; } - // display success dialog with any bone rule warnings + // display success dialog with any avatar rule warnings string successDialog = "Avatar successfully updated!"; if (!string.IsNullOrEmpty(warnings)) { successDialog += "\n\nWarnings:\n" + warnings; @@ -575,6 +652,27 @@ class AvatarExporter : MonoBehaviour { jointOffset.y + ", " + jointOffset.z + ", " + jointOffset.w + ")\n"); } } + + // if there is any material data to save then write out all materials in JSON material format to the materialMap field + if (materialDatas.Count > 0) { + string materialJson = "{ "; + foreach (var materialData in materialDatas) { + // if this is the only material in the mapping and it is the default name No Name mapped to No Name, + // then the avatar has no embedded materials and this material should be applied to all meshes + string materialName = materialData.Key; + if (materialMappings.Count == 1 && materialName == DEFAULT_MATERIAL_NAME && + materialMappings[materialName] == DEFAULT_MATERIAL_NAME) { + materialJson += "\"all\": "; + } else { + materialJson += "\"[mat::" + materialName + "]\": "; + } + materialJson += materialData.Value.getJSON(); + materialJson += ", "; + } + materialJson = materialJson.Substring(0, materialJson.LastIndexOf(", ")); + materialJson += " }"; + File.AppendAllText(exportFstPath, "materialMap = " + materialJson); + } // open File Explorer to the project directory once finished System.Diagnostics.Process.Start("explorer.exe", "/select," + exportFstPath); @@ -582,11 +680,18 @@ class AvatarExporter : MonoBehaviour { return true; } - static void SetUserBoneInformation() { + static void SetBoneAndMaterialInformation() { userBoneInfos.Clear(); humanoidToUserBoneMappings.Clear(); userBoneTree = new BoneTreeNode(); + materialDatas.Clear(); + materialAlternateStandardShader.Clear(); + materialUnsupportedShader.Clear(); + normalMapAndHeightMapNotBoth.Clear(); + + SetMaterialMappings(); + // instantiate a game object of the user avatar to traverse the bone tree to gather // bone parents and positions as well as build a bone tree, then destroy it UnityEngine.Object avatarResource = AssetDatabase.LoadAssetAtPath(assetPath, typeof(UnityEngine.Object)); @@ -610,20 +715,26 @@ class AvatarExporter : MonoBehaviour { } } - // generate the list of bone rule failure strings for any bone rules that are not satisfied by this avatar - SetFailedBoneRules(); + // generate the list of avatar rule failure strings for any avatar rules that are not satisfied by this avatar + SetFailedAvatarRules(); } static void TraverseUserBoneTree(Transform modelBone) { GameObject gameObject = modelBone.gameObject; // check if this transform is a node containing mesh, light, or camera instead of a bone - bool mesh = gameObject.GetComponent() != null || gameObject.GetComponent() != null; + MeshRenderer meshRenderer = gameObject.GetComponent(); + SkinnedMeshRenderer skinnedMeshRenderer = gameObject.GetComponent(); + bool mesh = meshRenderer != null || skinnedMeshRenderer != null; bool light = gameObject.GetComponent() != null; bool camera = gameObject.GetComponent() != null; - // if it is in fact a bone, add it to the bone tree as well as user bone infos list with position and parent name - if (!mesh && !light && !camera) { + // if this is a mesh and the model is using external materials then store its material data to be exported + if (mesh && modelImporter.materialLocation == ModelImporterMaterialLocation.External) { + Material[] materials = skinnedMeshRenderer != null ? skinnedMeshRenderer.sharedMaterials : meshRenderer.sharedMaterials; + StoreMaterialData(materials); + } else if (!light && !camera) { + // if it is in fact a bone, add it to the bone tree as well as user bone infos list with position and parent name UserBoneInformation userBoneInfo = new UserBoneInformation(); userBoneInfo.position = modelBone.position; // bone's absolute position @@ -682,8 +793,8 @@ class AvatarExporter : MonoBehaviour { } } - static void SetFailedBoneRules() { - failedBoneRules.Clear(); + static void SetFailedAvatarRules() { + failedAvatarRules.Clear(); string hipsUserBone = ""; string spineUserBone = ""; @@ -692,60 +803,60 @@ class AvatarExporter : MonoBehaviour { Vector3 hipsPosition = new Vector3(); - // iterate over all bone rules in order and add any rules that fail - // to the failed bone rules map with appropriate error or warning text - for (BoneRule boneRule = 0; boneRule < BoneRule.BoneRuleEnd; ++boneRule) { - switch (boneRule) { - case BoneRule.RecommendedUnityVersion: + // iterate over all avatar rules in order and add any rules that fail + // to the failed avatar rules map with appropriate error or warning text + for (AvatarRule avatarRule = 0; avatarRule < AvatarRule.AvatarRuleEnd; ++avatarRule) { + switch (avatarRule) { + case AvatarRule.RecommendedUnityVersion: if (Array.IndexOf(RECOMMENDED_UNITY_VERSIONS, Application.unityVersion) == -1) { - failedBoneRules.Add(boneRule, "The current version of Unity is not one of the recommended Unity " + - "versions. If you are using a version of Unity later than 2018.2.12f1, " + - "it is recommended to apply Enforce T-Pose under the Pose dropdown " + - "in Humanoid configuration."); + failedAvatarRules.Add(avatarRule, "The current version of Unity is not one of the recommended Unity " + + "versions. If you are using a version of Unity later than 2018.2.12f1, " + + "it is recommended to apply Enforce T-Pose under the Pose dropdown " + + "in Humanoid configuration."); } break; - case BoneRule.SingleRoot: - // bone rule fails if the root bone node has more than one child bone + case AvatarRule.SingleRoot: + // avatar rule fails if the root bone node has more than one child bone if (userBoneTree.children.Count > 1) { - failedBoneRules.Add(boneRule, "There is more than one bone at the top level of the selected avatar's " + - "bone hierarchy. Please ensure all bones for Humanoid mappings are " + - "under the same bone hierarchy."); + failedAvatarRules.Add(avatarRule, "There is more than one bone at the top level of the selected avatar's " + + "bone hierarchy. Please ensure all bones for Humanoid mappings are " + + "under the same bone hierarchy."); } break; - case BoneRule.NoDuplicateMapping: - // bone rule fails if any user bone is mapped to more than one Humanoid bone + case AvatarRule.NoDuplicateMapping: + // avatar rule fails if any user bone is mapped to more than one Humanoid bone foreach (var userBoneInfo in userBoneInfos) { string boneName = userBoneInfo.Key; int mappingCount = userBoneInfo.Value.mappingCount; if (mappingCount > 1) { string text = "The " + boneName + " bone is mapped to more than one bone in Humanoid."; - if (failedBoneRules.ContainsKey(boneRule)) { - failedBoneRules[boneRule] += "\n" + text; + if (failedAvatarRules.ContainsKey(avatarRule)) { + failedAvatarRules[avatarRule] += "\n" + text; } else { - failedBoneRules.Add(boneRule, text); + failedAvatarRules.Add(avatarRule, text); } } } break; - case BoneRule.NoAsymmetricalLegMapping: - CheckAsymmetricalMappingRule(boneRule, LEG_MAPPING_SUFFIXES, "leg"); + case AvatarRule.NoAsymmetricalLegMapping: + CheckAsymmetricalMappingRule(avatarRule, LEG_MAPPING_SUFFIXES, "leg"); break; - case BoneRule.NoAsymmetricalArmMapping: - CheckAsymmetricalMappingRule(boneRule, ARM_MAPPING_SUFFIXES, "arm"); + case AvatarRule.NoAsymmetricalArmMapping: + CheckAsymmetricalMappingRule(avatarRule, ARM_MAPPING_SUFFIXES, "arm"); break; - case BoneRule.NoAsymmetricalHandMapping: - CheckAsymmetricalMappingRule(boneRule, HAND_MAPPING_SUFFIXES, "hand"); + case AvatarRule.NoAsymmetricalHandMapping: + CheckAsymmetricalMappingRule(avatarRule, HAND_MAPPING_SUFFIXES, "hand"); break; - case BoneRule.HipsMapped: - hipsUserBone = CheckHumanBoneMappingRule(boneRule, "Hips"); + case AvatarRule.HipsMapped: + hipsUserBone = CheckHumanBoneMappingRule(avatarRule, "Hips"); break; - case BoneRule.SpineMapped: - spineUserBone = CheckHumanBoneMappingRule(boneRule, "Spine"); + case AvatarRule.SpineMapped: + spineUserBone = CheckHumanBoneMappingRule(avatarRule, "Spine"); break; - case BoneRule.SpineDescendantOfHips: - CheckUserBoneDescendantOfHumanRule(boneRule, spineUserBone, "Hips"); + case AvatarRule.SpineDescendantOfHips: + CheckUserBoneDescendantOfHumanRule(avatarRule, spineUserBone, "Hips"); break; - case BoneRule.ChestMapped: + case AvatarRule.ChestMapped: if (!humanoidToUserBoneMappings.TryGetValue("Chest", out chestUserBone)) { // check to see if there is a child of Spine that we can suggest to be mapped to Chest string spineChild = ""; @@ -755,54 +866,54 @@ class AvatarExporter : MonoBehaviour { spineChild = spineTreeNode.children[0].boneName; } } - failedBoneRules.Add(boneRule, "There is no Chest bone mapped in Humanoid for the selected avatar."); + failedAvatarRules.Add(avatarRule, "There is no Chest bone mapped in Humanoid for the selected avatar."); // if the only found child of Spine is not yet mapped then add it as a suggestion for Chest mapping if (!string.IsNullOrEmpty(spineChild) && !userBoneInfos[spineChild].HasHumanMapping()) { - failedBoneRules[boneRule] += " It is suggested that you map bone " + spineChild + - " to Chest in Humanoid."; + failedAvatarRules[avatarRule] += " It is suggested that you map bone " + spineChild + + " to Chest in Humanoid."; } } break; - case BoneRule.ChestDescendantOfSpine: - CheckUserBoneDescendantOfHumanRule(boneRule, chestUserBone, "Spine"); + case AvatarRule.ChestDescendantOfSpine: + CheckUserBoneDescendantOfHumanRule(avatarRule, chestUserBone, "Spine"); break; - case BoneRule.NeckMapped: - CheckHumanBoneMappingRule(boneRule, "Neck"); + case AvatarRule.NeckMapped: + CheckHumanBoneMappingRule(avatarRule, "Neck"); break; - case BoneRule.HeadMapped: - headUserBone = CheckHumanBoneMappingRule(boneRule, "Head"); + case AvatarRule.HeadMapped: + headUserBone = CheckHumanBoneMappingRule(avatarRule, "Head"); break; - case BoneRule.HeadDescendantOfChest: - CheckUserBoneDescendantOfHumanRule(boneRule, headUserBone, "Chest"); + case AvatarRule.HeadDescendantOfChest: + CheckUserBoneDescendantOfHumanRule(avatarRule, headUserBone, "Chest"); break; - case BoneRule.EyesMapped: + case AvatarRule.EyesMapped: bool leftEyeMapped = humanoidToUserBoneMappings.ContainsKey("LeftEye"); bool rightEyeMapped = humanoidToUserBoneMappings.ContainsKey("RightEye"); if (!leftEyeMapped || !rightEyeMapped) { if (leftEyeMapped && !rightEyeMapped) { - failedBoneRules.Add(boneRule, "There is no RightEye bone mapped in Humanoid " + - "for the selected avatar."); + failedAvatarRules.Add(avatarRule, "There is no RightEye bone mapped in Humanoid " + + "for the selected avatar."); } else if (!leftEyeMapped && rightEyeMapped) { - failedBoneRules.Add(boneRule, "There is no LeftEye bone mapped in Humanoid " + - "for the selected avatar."); + failedAvatarRules.Add(avatarRule, "There is no LeftEye bone mapped in Humanoid " + + "for the selected avatar."); } else { - failedBoneRules.Add(boneRule, "There is no LeftEye or RightEye bone mapped in Humanoid " + - "for the selected avatar."); + failedAvatarRules.Add(avatarRule, "There is no LeftEye or RightEye bone mapped in Humanoid " + + "for the selected avatar."); } } break; - case BoneRule.HipsNotOnGround: + case AvatarRule.HipsNotOnGround: // ensure the absolute Y position for the bone mapped to Hips (if its mapped) is at least HIPS_GROUND_MIN_Y if (!string.IsNullOrEmpty(hipsUserBone)) { UserBoneInformation hipsBoneInfo = userBoneInfos[hipsUserBone]; hipsPosition = hipsBoneInfo.position; if (hipsPosition.y < HIPS_GROUND_MIN_Y) { - failedBoneRules.Add(boneRule, "The bone mapped to Hips in Humanoid (" + hipsUserBone + - ") should not be at ground level."); + failedAvatarRules.Add(avatarRule, "The bone mapped to Hips in Humanoid (" + hipsUserBone + + ") should not be at ground level."); } } break; - case BoneRule.HipsSpineChestNotCoincident: + case AvatarRule.HipsSpineChestNotCoincident: // ensure the bones mapped to Hips, Spine, and Chest are all not in the same position, // check Hips to Spine and Spine to Chest lengths are within HIPS_SPINE_CHEST_MIN_SEPARATION if (!string.IsNullOrEmpty(spineUserBone) && !string.IsNullOrEmpty(chestUserBone) && @@ -813,34 +924,34 @@ class AvatarExporter : MonoBehaviour { Vector3 spineToChest = spineBoneInfo.position - chestBoneInfo.position; if (hipsToSpine.magnitude < HIPS_SPINE_CHEST_MIN_SEPARATION && spineToChest.magnitude < HIPS_SPINE_CHEST_MIN_SEPARATION) { - failedBoneRules.Add(boneRule, "The bone mapped to Hips in Humanoid (" + hipsUserBone + - "), the bone mapped to Spine in Humanoid (" + spineUserBone + - "), and the bone mapped to Chest in Humanoid (" + chestUserBone + - ") should not be coincidental."); + failedAvatarRules.Add(avatarRule, "The bone mapped to Hips in Humanoid (" + hipsUserBone + + "), the bone mapped to Spine in Humanoid (" + spineUserBone + + "), and the bone mapped to Chest in Humanoid (" + chestUserBone + + ") should not be coincidental."); } } break; - case BoneRule.TotalBoneCountUnderLimit: + case AvatarRule.TotalBoneCountUnderLimit: int userBoneCount = userBoneInfos.Count; if (userBoneCount > MAXIMUM_USER_BONE_COUNT) { - failedBoneRules.Add(boneRule, "The total number of bones in the avatar (" + userBoneCount + - ") exceeds the maximum bone limit (" + MAXIMUM_USER_BONE_COUNT + ")."); + failedAvatarRules.Add(avatarRule, "The total number of bones in the avatar (" + userBoneCount + + ") exceeds the maximum bone limit (" + MAXIMUM_USER_BONE_COUNT + ")."); } break; } } } - static string CheckHumanBoneMappingRule(BoneRule boneRule, string humanBoneName) { + static string CheckHumanBoneMappingRule(AvatarRule avatarRule, string humanBoneName) { string userBoneName = ""; - // bone rule fails if bone is not mapped in Humanoid + // avatar rule fails if bone is not mapped in Humanoid if (!humanoidToUserBoneMappings.TryGetValue(humanBoneName, out userBoneName)) { - failedBoneRules.Add(boneRule, "There is no " + humanBoneName + " bone mapped in Humanoid for the selected avatar."); + failedAvatarRules.Add(avatarRule, "There is no " + humanBoneName + " bone mapped in Humanoid for the selected avatar."); } return userBoneName; } - static void CheckUserBoneDescendantOfHumanRule(BoneRule boneRule, string userBoneName, string descendantOfHumanName) { + static void CheckUserBoneDescendantOfHumanRule(AvatarRule avatarRule, string userBoneName, string descendantOfHumanName) { if (string.IsNullOrEmpty(userBoneName)) { return; } @@ -867,13 +978,13 @@ class AvatarExporter : MonoBehaviour { } } - // bone rule fails if no ancestor of given user bone matched the descendant of name (no early return) - failedBoneRules.Add(boneRule, "The bone mapped to " + userBoneInfo.humanName + " in Humanoid (" + userBoneName + - ") is not a child of the bone mapped to " + descendantOfHumanName + " in Humanoid (" + - descendantOfUserBoneName + ")."); + // avatar rule fails if no ancestor of given user bone matched the descendant of name (no early return) + failedAvatarRules.Add(avatarRule, "The bone mapped to " + userBoneInfo.humanName + " in Humanoid (" + userBoneName + + ") is not a child of the bone mapped to " + descendantOfHumanName + " in Humanoid (" + + descendantOfUserBoneName + ")."); } - static void CheckAsymmetricalMappingRule(BoneRule boneRule, string[] mappingSuffixes, string appendage) { + static void CheckAsymmetricalMappingRule(AvatarRule avatarRule, string[] mappingSuffixes, string appendage) { int leftCount = 0; int rightCount = 0; // add Left/Right to each mapping suffix to make Humanoid mapping names, @@ -888,23 +999,23 @@ class AvatarExporter : MonoBehaviour { ++rightCount; } } - // bone rule fails if number of left appendage mappings doesn't match number of right appendage mappings + // avatar rule fails if number of left appendage mappings doesn't match number of right appendage mappings if (leftCount != rightCount) { - failedBoneRules.Add(boneRule, "The number of bones mapped in Humanoid for the left " + appendage + " (" + - leftCount + ") does not match the number of bones mapped in Humanoid for the right " + - appendage + " (" + rightCount + ")."); + failedAvatarRules.Add(avatarRule, "The number of bones mapped in Humanoid for the left " + appendage + " (" + + leftCount + ") does not match the number of bones mapped in Humanoid for the right " + + appendage + " (" + rightCount + ")."); } } static string GetTextureDirectory(string basePath) { - string textureDirectory = Path.GetDirectoryName(basePath) + "\\textures"; + string textureDirectory = Path.GetDirectoryName(basePath) + "\\" + TEXTURES_DIRECTORY; textureDirectory = textureDirectory.Replace("\\\\", "\\"); return textureDirectory; } static string SetTextureDependencies() { string textureWarnings = ""; - dependencyTextures.Clear(); + textureDependencies.Clear(); // build the list of all local asset paths for textures that Unity considers dependencies of the model // for any textures that have duplicate names, return a string of duplicate name warnings @@ -913,11 +1024,11 @@ class AvatarExporter : MonoBehaviour { UnityEngine.Object textureObject = AssetDatabase.LoadAssetAtPath(dependencyPath, typeof(Texture2D)); if (textureObject != null) { string textureName = Path.GetFileName(dependencyPath); - if (dependencyTextures.ContainsKey(textureName)) { + if (textureDependencies.ContainsKey(textureName)) { textureWarnings += "There is more than one texture with the name " + textureName + " referenced in the selected avatar.\n\n"; } else { - dependencyTextures.Add(textureName, dependencyPath); + textureDependencies.Add(textureName, dependencyPath); } } } @@ -927,7 +1038,7 @@ class AvatarExporter : MonoBehaviour { static bool CopyExternalTextures(string texturesDirectory) { // copy the found dependency textures from the local asset folder to the textures folder in the target export project - foreach (var texture in dependencyTextures) { + foreach (var texture in textureDependencies) { string targetPath = texturesDirectory + "\\" + texture.Key; try { File.Copy(texture.Value, targetPath, true); @@ -939,6 +1050,97 @@ class AvatarExporter : MonoBehaviour { } return true; } + + static void StoreMaterialData(Material[] materials) { + // store each material's info in the materialDatas list to be written out later to the FST if it is a supported shader + foreach (Material material in materials) { + string materialName = material.name; + string shaderName = material.shader.name; + + Debug.Log("material1 " + materialName); + + // don't store any material data for unsupported shader types + if (Array.IndexOf(SUPPORTED_SHADERS, shaderName) == -1) { + if (!materialUnsupportedShader.ContainsKey(materialName)) { + materialUnsupportedShader.Add(materialName, shaderName); + } + continue; + } + + MaterialData materialData = new MaterialData(); + materialData.albedo = material.GetColor("_Color"); + materialData.albedoMap = GetMaterialTexture(material, "_MainTex"); + materialData.roughness = material.GetFloat("_Glossiness"); + materialData.roughnessMap = GetMaterialTexture(material, "_SpecGlossMap"); + materialData.normalMap = GetMaterialTexture(material, "_BumpMap"); + materialData.heightMap = GetMaterialTexture(material, "_ParallaxMap"); + materialData.occlusionMap = GetMaterialTexture(material, "_OcclusionMap"); + materialData.emissive = material.GetColor("_EmissionColor"); + materialData.emissiveMap = GetMaterialTexture(material, "_EmissionMap"); + + // for specular setups we will treat the metallic value as the average of the specular RGB intensities + if (shaderName == STANDARD_SPECULAR_SHADER) { + Color specular = material.GetColor("_SpecColor"); + materialData.metallic = (specular.r + specular.g + specular.b) / 3.0f; + } else { + materialData.metallic = material.GetFloat("_Metallic"); + materialData.metallicMap = GetMaterialTexture(material, "_MetallicGlossMap"); + } + + // for non-roughness Standard shaders give a warning that is not the recommended Standard shader, + // and invert smoothness for roughness + if (shaderName == STANDARD_SHADER || shaderName == STANDARD_SPECULAR_SHADER) { + if (!materialAlternateStandardShader.Contains(materialName)) { + materialAlternateStandardShader.Add(materialName); + } + materialData.roughness = 1.0f - materialData.roughness; + } + + // materials can not have both a normal map and a height map set + if (!string.IsNullOrEmpty(materialData.normalMap) && !string.IsNullOrEmpty(materialData.heightMap) && !normalMapAndHeightMapNotBoth.Contains(materialName)) { + normalMapAndHeightMapNotBoth.Add(materialName); + } + + // remap the material name from the Unity material name to the fbx material name that it overrides + if (materialMappings.ContainsKey(materialName)) { + materialName = materialMappings[materialName]; + } + if (!materialDatas.ContainsKey(materialName)) { + materialDatas.Add(materialName, materialData); + } + } + } + + static string GetMaterialTexture(Material material, string textureProperty) { + // ensure the texture property name exists in this material and return its texture directory path if so + string[] textureNames = material.GetTexturePropertyNames(); + if (Array.IndexOf(textureNames, textureProperty) >= 0) { + Texture texture = material.GetTexture(textureProperty); + if (texture) { + foreach (var textureDependency in textureDependencies) { + string textureFile = textureDependency.Key; + if (Path.GetFileNameWithoutExtension(textureFile) == texture.name) { + return TEXTURES_DIRECTORY + "/" + textureFile; + } + } + } + } + return ""; + } + + static void SetMaterialMappings() { + materialMappings.Clear(); + + // store the mappings from fbx material name to the Unity material name overriding it using external fbx mapping + var objectMap = modelImporter.GetExternalObjectMap(); + foreach (var mapping in objectMap) { + var material = mapping.Value as UnityEngine.Material; + if (material != null) { + materialMappings.Add(material.name, mapping.Key.name); + //Debug.Log("materialMapping " + material.name + " " + mapping.Key.name); + } + } + } } class ExportProjectWindow : EditorWindow { diff --git a/tools/unity-avatar-exporter/Assets/README.txt b/tools/unity-avatar-exporter/Assets/README.txt index c84cec2978..2aa1e5f02b 100644 --- a/tools/unity-avatar-exporter/Assets/README.txt +++ b/tools/unity-avatar-exporter/Assets/README.txt @@ -1,6 +1,6 @@ High Fidelity, Inc. Avatar Exporter -Version 0.2 +Version 0.3.1 Note: It is recommended to use Unity versions between 2017.4.17f1 and 2018.2.12f1 for this Avatar Exporter. diff --git a/tools/unity-avatar-exporter/avatarExporter.unitypackage b/tools/unity-avatar-exporter/avatarExporter.unitypackage index 95c000e7c61b7623e0da0a1f9974e0744375014e..ab39e1ed8f7d25ceb210c8ee59897c88aae20abb 100644 GIT binary patch literal 15949 zcmV-TKC;0diwFp-Du7%B0AX@tXmn+5a4vLVasccd*>c;+G0*x6m=9SgmTBIH6(z;B zXiJH%kW!MZ*rkFvp^FFa3;v#ozU2t5vHt+KqPeC$)OL)@}U6Yyae5@LMOTzxoMK z@W1)n*#ApEy^s7w@RP^?0O*GP?_~PF(SaoIU(zT4|60+BgWPpg)$gGmasC)M{s6s*F@!OqTP4g)E}X77!67Dw^- z!98#`Ua!2r?0E2l#;%uB;JWvj^B`I;ZlU-L8W=#@gLgRsR`{tmx%Z>HAc2oCAztiz z{yd327_uD3R00VjZ!{bnoeilVVFJ-l!-)r7JdLCI1AMQrA%ouzt_Gu<;qNamMpwhp z&2NXJ@yW%xcj#4W)n>I`IiT835VLs5OJ0wLmCi?4X#h2nFC<*$>8+nd~h~oXuWfPAutP>xVkvHc;l^;007+uUkf1r;iCt{T%4T^ z&yR*jH`nJUS3ihO90P(V_##W9%<*3Z2X3`dtv6=%%D$akcPH1J$$e*P&zahFrgogE zZD(rBnc8%w=Csb4TAMYj)Oxk=N~N~hsa z!%kN1_;#?9H~5c2(tG~u;pa@g_PLz>!aKe`8=PO99Nk=9+#H|0JGuGQ#mV^Zz5psnkbZ~I#2F;D_|^lv67Tqcl1|C%|c!7TMozz%&S%jD0Y z7$qM2(Uj7gc@^OQpvD)$Gz3j+Rcqu{yIjRz!-WG=-BIN%qwn_rYbdZDoL`k z6a-#dOVN zCfH?#ZW151a-tlmon%q?+g;2g&{j~)f0B-rnMd_aPfPabH*;Fz-zM>Vo#L!y7OaA3 z0)NG+PxD_kV})tBcf4NsQ5-@X0j5+Qn=cPmFkQxZ>+M&Vy|D?mr_Djix|qLN`yh%D zr2YctJ@1C2;rZL)&FJE4aHS?Z#TA_{CRI~qc3;8tv)5>K+RfR%2flW@(QO5J9jYNldL% zYc}DNuo^I#S8KxrAhlMr->O5c8Ulr>MYq|lbr`j6n94Q!-8N8bgS6dY7bAe?UZ>XX zQfpiNTCdjYAtL;!HyZsuePGLKO~|n@xNMn?hrl&k{RYBDXq`rrxbliVTFn~rgq7;_ znr$0T*7W7z=ye+XCdX0lwi#IZXhKH{9MJbIvn{rVo{OSZYj+riI?&yg82asIt;;d= z+JL$M!)A6tw=}zr2Je=3tI=-DZfW;=U4gaLYBpN=h>G~d`k~$EaU@-UBzvLTY;^>V zM!VnX*f^LG-N3G1x8CcuIlmgsR*g{5N4r+T_OVjUX0Mrtq7=XC-Fm0Z`PFN5d(^B~ z^wH?F8Ukwv)+77*h&IVryWQ^#8E(~UfKc>9v(uG5)Q0{yW!Rp=pkrOo>tNN>wAk76tv)oyib-8?j#M5_VxH+V~GfKkd; z7gUM-=(l=xyFcuSm5rg(fi4HAh@sKz0qZ!gnw=WZEu^w=2R#ju%K9RS>EFa=rf z_hHmiHy~2b1jI!w)r8M}rcdmtTW(uAAV0h<-Cn!f;7w`Qpa<%rDV=&fGfL!C@44-f zm=)S^!FEDJ>usS1n;jU+bw+!?*=V+frmBH)s&{H8Pt?rPJpj7>ZmY&eSRG`sBl@w? z?RSJ^LiaYa`qi9}x`Bf!?=}%Q|GOcqTeI7O&Qu@WjHxpxv2KR~guL0SwM1{#n)P<8 z-D`3;q7S0Z{syhr?1G)LWm3&}ofw+E7W5dmJ&iU{vlx{&GhJ`ErKcfBL|+-=la>Z9Iox`7umz0(0z zUq>R@XRp%&b;h`kzYeK3#`b0tJ&-+XcK_Ui$Bqlw7?_Fg^@WMA*E@CPd9~W4*{BdG zAmDo0D1wEig}o-B0dH83(nl8%as16@1BYsvn1cfaP}~=03tUnunzdRF6g)@K1AziR zqC|wk#?b47-R80n1FPN?ji}c^T!r0lHQQb2;L`C7SD&=%UBMH?qr9$GqbV#u{$_in zf*&>tXh>I3jMIy*^15m@Y5beb8uZOxiBO4yS)FdD!)-70MyIcwt{(h2vtZ=l)TVS? z#coNx(}i6J99**r21@!|T{gL*Lg?Vn_DTg|9HP~Mq0kmgsdt$l!8p`!_XQif{T__M zjS-s+d@lI)E+@6t0IQ~^B^{D!l0Hy`&>JNKJT9?>QiV{48K@qtldr7Pt=WzVfpg4Q26RR5V;YS>S1rqXnUl zhH$jHfIxX#jb2Bx#+nwZ2w)EBb(s1{Kdaf-{H#uwcV(-N{WR$k*#4`^H1<}-p z%{;{$J5Go1VZ+GfC2mt0U%z{I^7~=YmJZcJDou?OmBv(w`X*r%?JA~dFgn|YA~l3m znh?*v+JBrtL_fe1}IAGVyy^=u3m&3Q$r-P9b=6D%Q)^mSV1|&%9`1+DI=YfWM6u|z>MF7KMN=rI?Bd3M{sGSER&^RjX zJU&`4VVfq1!x__;dfp&;0Ep=d^5>wqHk1IRv7rR&5vvHUrC?$(RcT~`oQX$4GC_qM zr57`-sj|tgusWGUy$%6U`4~^g*1-iMSDFrn;Hqr!GNFo3_0p%7F~uW`HXX}Abg2~7xw0{XWDVFg!^oUpyB{tEW*^4-LK z;svW!yh=Ri32(UyJ_AxOpnb8lG#A58-_@5e2{?o=;e75T_wg63`o&*GP|9s76*({> z*cR5C?@uq@{u&Jd-`P64J{88mEdLirtEz@z*xAIwf_&m`LB8r{TiLN)!`Df$!Y(+8 zz-w60(yB)3a(xQ}M`)gVbUSeO=mD^wR$H0l5k|@*31?oIda&}kAhbHSE0r9$OMeAj zBmnbI+>N?YNHSG%ORn&KNP4g)-^+|HPZ}=x)@1^r2-1no!u)M8fgRaRZy6^cGU7mA zgO;h;TFSqp#c8V|Pqix|+pktZa2`(spi+Gt$dZ{VuHM?+!~Rk~)k|m)Nbjqk;o9%+yXnLE zbQK83*d_E97fA}X?^|I3MjefsjBH4XkqVvgJU*OZ_l5ra2sDbV7T`1j%ryM@Z7_`w z+&tpB&^K0rX$=1c-XZ`a0N*(PWPSmNmGGZ(V5kBvAc9>upymYy?gN~b78HmllldCm z5mCnG74At%!p}ht2$^p{$SHdlq`w+poM*?s$o^wOqpI`bFX+S|CMSG(je8*#=p! zL?dKbqZKl>Y%}tSVS};+C9#yc8d%cPX^^U=1R1idL5WN)ON<6l zXeBxRMS{=(M%ta7#mz7sS`C%5IGce@ylLbG^x6r?IaLkp(N!u!1lHYZoNia&=`xIRspKXFeQfoT?m7+JM3D;}HIGmf*o0{*B;61hvNZ zK12v~2f8%HS=iT6vR=|~;!wBcijH1cnn5%@78)O79^b>>F#Os~Q5JF||qmKPE&a_z}D8q{Aejv{q2Y6Um$nWk99KC=y*xruWw; zM>LyKhMG!NPlME!f0#O?J^|;bi~?f8vw_6Xg~F8KPENdiqDW6h;-`UKvuLV`iiQJCpUC z;URND3l`**LQ^?A5`*FxMjW^^T)2z(Noer{yM6(p0|_k4o01gn zYw)o!T>=8-U^+PsAmM>U_#G4irX|cdMSsbq6@8fn5khs2E7Q}&+aV)UO_NlwqS$(TAu~(!6n2JO-lrsc~!blCfNR(C2L7XOp+Cns1X?xw;QzebiVwa3UAopD0e* znLd(}m0AGyKKoFXYbnZ$n1v&X)eMurIptC{Jd7OEk|(hbrH`|Zu@1-dTEXTmFzQGd$!A#AV`j)?l%Hk0 zmp&}ZFu^TQg_Ehru|rDJJt&@AoRj$+3#wa4uQ$Xq@1>S`ut6nOIO|khfi=(J7Fz;>1q??IMl=-0iT6B=a6{ZG zUQl~sQ7d&BQQAcSNPweLR4x83fZ54ynfj=X*S8GBZf##rKLt#}b}+TOw|B6;=cgc+ z^tZAmavD$8pyATwT|B2ahqy{?7<~>`afEs3t+Q-4>97mnZX%$J6{?;+90{m_F{4s4c^dXdjdDdkxPCRvl%%M zMRAY=*P2-fdy1f$d}?+SuE^zms1nL#S2hhO`la5`H`#`o(6dq+gO7@{d78$bLzQpt>Wjs|kK@Lj@ZpBWjv0J?DQ zcl_-;8u(0N+**1D0eM2^9 z#t}l0(Lo_G_wW2LQbB`9jPiVSM*5woRv|E{yRm;WYzjRUYS1>m!NhHFP(;q{w7*2L)OC+cCQ z?Fbr`MeyYLVG^QdNfz)U&|p{Lf`vL+6Mwe~SsK?t$X9f0WV#(sv;ne4m4>KuSi#Nq ziHpWxI1v>oyO_tHiiXi!xDIw6e3he#O*0JHDK%CqDhkOv+Yk%hv03Ths5GXO9-I}1 zj3z8cG0ktkz^-1mj8wBi!qa|P*)M_V2X?#Ad5r&mONPA2P6)Qc#i`sEV0C1LGPS z3&e@nV0$R;youRI0TnW2s55e^JyA8;g^V3I0XP z0(f&9ECk#`42{JLQI01NOqC!koIlFKWcF9Iinn|t@z)2EyMD58&GJmAFmmDAeC2_B8 zuQA$TD;Mio+4*Qq*d!~SiFp=f*lT$-U41vcGC97lhe0u%Rgysc%caV=%Azd+bFm&u zl%d4v^O^4wnLQOTJ9(y8?q`8+oN7CJcypPVa0Ld%BPmA`U%Hfsu&5)~VGj;xop%Pv?MDAslC^xRe zu?%+j8Ipq}`YvU<#%6B8vLdpU2}b6p>aaJn{zk73vS=A%QnYrFu$uDPNp1z_K?)F{#< zY1o|`156GlJEN8s&xcx@-*2y~?$wto6vY z(cTQf=B5UqY$diD#R~#QHV=8*{FJGcB_+d6+tpCB_NwqVwv-2MS92PzU_+~)?5mX6 zdHnD6O`hURlxrH>`h<-W$Kn&%?Q|cI*xSumB1boQ92$HI3`vE8*Q(&Nf(bYhXaPgW zoKh4CK;6MbW9<44K54Vrov^URWBeA933Oc0!N^FCB=3dGMj>B|eU^>>%D0{T%CJW< zc;lVSFcg9UBDY>Tnok_Yg8XdfzE`-+Qd!a@L!1wSQyuUjU~yqwhBVhfK(+!qD0fV% zlz(NJF1FK34qBHAa9JtnjzR?lZCdedH*8?WOB`E57wy=SOv9KEJ%c$7w5%ejkV|n$ zyiyeL9nu)cragYshnM%TVd6uSz_m`8RR0hmW>&e(5ev)WkzCOmjxZ7dhUh3r2ku%E zU$4AtY|nZbC!b-W`{XzXQ()PBci)QbPbLNd4U%2&+)!;CS_YkGd^jl{M=c;v= zj8V_t==dw3k#8X?dWG;04pj0MnvVzW2+4qMZOoHk;tr6>1W^(rrH!ZSh{d*WC2X=Q zHgpQeKVBx6k{hnNC_g4-ch&e427KZOiGjUs3IC)PSfT!^$ab9R&;iNjL4WHY-B+T> z(yYVeXH{HD=8}hIfFN}}*#h_9F6R$fBH(#yPA|`qH+wyvP7;zoD87AEg?^T8%vK?!JA4!x zL?LHr;xM8E1oHNUSL|9eYFeVN-ht9t`EY7P&(9G#hU|h+Y`pl3Ng57=_ zs_1gcnZbROUe0RdoW`o|biD{x9;C@Mg#aQ9xUVnRbqdiQ2*_$XDYsZ+D8gqW>>$Tb z(xHn{@TYYMQ>9B1dD{LLO;5FqK{SC`LyT}ujhVBa=K%V`(mnQYPyJ7{BS}tR_{c!R zrZhkZL!CuPChHZ#CVvN3SLlRI00)U^rp3kx;};<;&46Pe7nV-2%YI~1r248rHtpJ@ zVrk7IO^Ixgbo}fvALA3(yOJ;dlEtRx@Z`#?d!LT{?NX3xkG7XVh*qT^hws8YFq`pe z8saI$q>QJ+9hH*t@60fAX`f<6_)5#I!k#Ss^TGW5^S)=4{<8OYCsFhV1I7J9)|jlv zxQkf^mFzC3QhNZiKeK%jkl9Xm@)u0r+ul!==j1}{{|9v(a0+n*=xw@7gS-uWNo_ut z1u0m9x9X{?%mL()A^kQTHZ?Wk55`qERd$i)FYIFwnUjydk~j4!3usSobl6Cxfvd>d z0$#v>Ks+t+%6dE+DkfMoUc!_Y<>!%j?EO6UKuB0onp%pKeb?@H;;+8v=iX<#P2g@; zJY1)kjW~%wnWP=F2V8R&(qKIlU@Xf*=Q>1sXz&JSJ#G_{xfw}x*da{xy`TQnfQgAm z!*_%0(<`|69j<{n8Jv;_fd!pIBMbZwI=GLy@N!I-k`?{_!#Umc#~N446Uc#tw7q%b zIx_o_VJNW?#sq720iW^83o8#c*4}VAU1sPQpT;pFBgZ(C2^i=^W+4@H8QhjSR{)W7 za|3L4AxQmpGAm?+%Nx=G!Ge_-7}OIC@Q%LAs=R$u?eA$1o<- z-HJGRSPj0?OTDkzVZ8lJsK{P+Q4t;5^>a|Lp0#1)oi6O=^!Y8sn^u~jZaJ_k*eCk)iWVMtw@d3cnw({HOx`^vAuV&lnN8XnbcbU*re#pRRzVzN z+L{U4$|px3^H|(J1>Qjp)J6MhK*s`NLQfi9?jAL!leg;-^t!LW?K3+u4Pdaw5BkP6 z^6`ez9UjSJ%e9=gQIJ5yd=gmKCY{Fq6jJOh!TYo=IiBs>F!jOz9$3OLQC0PgPLcZB zJ5ik6HEG&AFxh^^d3db}<8B6c6&M{QI39RyRsD#uj+Je_CBJ-^He` z;hR3RoxULkOH;bfWrZPLHqfL~FhPr`9+aUv8a};)fjsQdP~nve_oDM<4q#L?WbeqK zQanyb1#)79nBWQ!%Iczp^lxrdP`@voN@~-s5Nz;y@Q9N_`lw;Izn` z+}Xyo}XHa2;OX%q8EcA~TV@23qhWG69A`?F)8u9b9RrFxuHBAjYQxYECg9@Vl#X<`&d{O9h+&cHEOipIU{g zTWw{KmkG($Y&DT%rX0g}xC1@0=iRq~ShqJP%!KBrKg}HM5Yv1T@jF*aecs~<+Nd?7Qu?qfB53J0^uG>xPo7tWg0%86P#%_GJ<~G*>DOmf{ zfmTI3$i2~W0OS@Orar8*1-UdyjMAS{i_`}jcb~yZNx~)`$~&N5)A~kt*1g>jSAglE zA^7L#T6a)!{;JcdQTbk#-q%YKaVuOYY2r zm);`_WQr}z`M7y4Ryyng+OfKk8xw>!V6MYrW z=#f2fT_sjw#sGUpZFnG~tbn=5)kWh`^H%ejV5?=@OknM` zFX$UQ3mECbMhb&&v{Wl(p3D)8Vt6Ggh%9Afq}AzHO)$rl*C&rOT2k49ordHS3?}*} zaeHdJ=?2SeRQtF^w-?Yj!p+%|yuGdJTH=yvSjNC_w0Nj1-LVFJFwC;K`JreP=vpR% zD))WO2|j08ScJ8$xCm~_%_$-N5YH15O_v*AF3by|;>x2D(LoanTMRHKnxcma|2}BJ z9%7pgj!(llJ55+H(D+XKB`oVK@iJp^BP;xeo6p5z6w`0g?y~mfpX5jB-#^#i0X5!H zMW;#?wC0ux(1dYRRm8bN5rV}!hMbpq->8a(*K3c4Z!gZyhUZ7{0`c|v$<+_yoej8L zdw?s!e4@YBVDI77>{Z=GU7i%P(WF{N7b2)#KA#z2wCB_aVbDR)AT4_VH7oPT%@N{P z;W(43QAB5UfEuo@ZdIWH8|B*q_6G&vBR^*^PJEf9ZM7+AI|YNtwBb{J7;SS0 z?pDJt^N4@p;CqWJS$YLt8bKM&JRQD=%~_Y1cz$qv{qEh#@A0XR$~?FO57G7`^CU zKpC4OZBH7(eGb}iiv_rVK5oXv_7?OpqtdKGlxE2@8ud(!q{(oWk=q0y%Et{X@Y!{7 zb`yV~#bD$@1^QRSSN_CAfLGm%L(+U{R9PP$7qou%ESf^xj#D$`_OcU*Qcbj0K%lDp zvSWQZ;LOU#X3MFAw%p>w!_6iiekOO^5a9(qxn<{h%~(16XH_Zs6nAko9DaT3yK)!ZN>ug*`aSldQ81I>RkCi#<7}vsr$}O?Du#x4K zm*kz`3|F*?n(L=H-NqIn_nC93sMzL!wDVVylnA*QY z=ewXFD+jzRyJm38>M0U!*mOwjQNTyMV$pTtFAU0Y&({kRpHN$Q0L=P7{pmLKA7N=k zoAQiJnHw!O{VIjNoEC&KCK;l#ZwR+0vrVWxy_U38P%@7(WROlZ`GQ; z`8Mi}zsepzvPkaqEydUGNYGe#{of(&HGnmxB?VWZ!aBne$&XGwyQ2$yMcYJM%{vzC>m2_@&$u1K0(b+La5La!Wwg7um03 z)`y3t!g$3Rv4zIqK>5@?W&&}T1ta0JrfdNpg+dXG3lMj(vWjn6|9q2>vHs8h88mML z_`g~I?PtxR9N89b#-Ha!4%)*-0Cj;y027wyBp{>xCsNz`|8muT6$4Ui7sbo2arN^w zT!iVHyw|DZsCO;T@zd}J8<()fdfeII_a|r9XE)d5;ppc33zT#)@K;Y?%Jx!h80^7c z+~U)BGj60p{f+_ZU9&w;>s{#C;OhjQS4j9J317p-dcmY@j$9>-d5xy)E1tf@ym>Dd zvpMuZ)|l6HmEZl%bIRVJm_b|mK0`r>UH>pwumJxP-hIKJ zlCvz~WsgpkFdz8asK29FQh+^r7k&;RDNsTLn9F7Ny|)Y1VVCgyfwz5cXFH{wb>oCp zH#gx6C7t!}RM}EbO=S!|w_5tbZR(`R)Tj9bZ5c$%lP=**Y&IPFo{Q2>03MBHWykB; zEc_ZI(r!R95_D(UiYTR!y>J?92YMC@*Qz{2-lkIuLcXT(BQg^;j$Beq2t6c2%BR5E z6DSTu84z({6LDcrWj#cf^^PNk6VF=iRjR+S0ZLlsE>iIl3)5O! zdBpClV7MZZEoib7!H;t{%Sfm2EfFy)8c88jF1y=rh?PwsC4&4w9mg3`cF=IL7z-Y; zE7xv?#!ar>%AeG9J;cGY@Gc;_vC5vwq?szYPsK|Z>XmqWJK%aW9N!$Bz%hlZi_s5? zSR1aDR2{L0kaqzb0Nf|As=eG&TGbAU*)UdY&>o-I&2PGR+aTkbrdc3`Cw*SOW_S6R z*P_hl?0!^sc@jM>LHoKnaDFz1onVkB-IEfpW&k>VuZjtZUBEgOd#$-?5S;XR%K@fY z#(p(R+CYPt?EO+CC0f4ymac6@6u<{82m{JMA^Iu*&MVPk_O?)o}oa18yURC9Y<`eWLa7G!iV$un!G2Ia-W={ zwK3HaSyMhlrRx&&9V%ItC%YfhRWGdDCm{p`sA;o2&$DCj`BO%AOQoR@S#&I->^qpq zRME@qNW?zJryf@Q(cZt=`kShXt}T6lC%+()eMMxm(^&e3O6zhS*PTJ8 zH1nH|P^x5+?-B~Os9SXvM7&=|?DeI4htnX!AO;@hQ?d*n2qA;~dG6cPw$9@U~y@%%&lMoA(15=8y@iLeIU@Bb* zmfikZ3g-9g#c~t4d%8fj6gaqW0z7yB>n4!#WHMjlDdbX6FGT50V1q>nZ2uhOh{+JL z5zJ(jxAD=3!&AwEe&PNp)cG#Hx8 zRM9NF|5gC4u0UbSk30S2cF%k5HLJB*$!N6`SI+o6s85yjCf zrCa!g(8BN}6gl^NG2^6ZD~~W|?-9t>-Or+9ck|=pD`5W?uyjHwi3mYJc~K$>!p+K$ zmo+kc8?VIvXM4xm<1`H0=SlpB!WRY_y|#OyLm=_k!K8yjcLyh4LcO+wiqVd?V@&*c zY$s`wrh6QZ@mi38wTa`zj_cS?%s+n@`}Ud8%rD@^U%jQD0T(#cy0PT_Mfjjpx9C(? zl5)!gWmxk0&E9BILkhwJCY|X)9&MU;r2cb3!Dt&aU|p6CR$VrJ0g|l(W6o1E`q%+oE@KsmPWiDA9g2de*3B(1|HbaSCmGohqb^WqRxbH-Snwt8e z_Wr^*1~D$Hk*MY#q+PKUJA0oR^Ml|z5?i|%-q+`~ z#o5eL!^WqYe5%Uesg5pHK^=Gbu0aLXHivuXwwd>ZcOoj+qtL2=T5h+~!JEbo!@{xH z(Ckrf_M?0hw@sjixkJOXY9%}aLmcdV(Tf{UTY38jq_-+*dud= zguH1W)_MaP@Ak@-RaS-i&{V?+TO*iS+%r$crpF}^LDa3hqTYZh`bx3`vx^IB_m z{p9Q7lK8GIx<}roC(6hqVGOHA36pFa8c5_yd|HLP{{A-Dr3Vuq^p+vnH=i=|=2@J; zy-U_UxB2m(G+1)66y%LR8$Ee&boTaa^x*UnOlr?@Zq?U#G#ovAbP83veWS{~XQ!t} zPu?CJL2iJP(aRw!Q2lD9!@Ku}hpX$*T77#k8Xi8-D|VMxl!$o-Uc=+#qhlSCSFI!R zf1lhxJ~}*<(AM!(J(R zz#q1j45TjAce{dW&N{1tv{Lr_KJ3iS{osR%5g{@HNx*v-S6ky(#^|JNzz{Nw~ZPRTlkR-$C)P5eSs&R6gzzDG_} z#mLg?r54BQ|M&uXK@v!at0kk#QQd=A6D3S5q15)}Kufj2T0T}07Xrf-)hh#7s$VM1 z8^NZHy?-7@^Hyz(w$k7%4vY7i26e5yafFUp6v*rw*s9$XTw6g!MV~Sz!fZ24LS?u= zL~JGq`Eti26~TMvfr8z9JYI-p!&e)wFP?X1vQX436(l?ceT?bCq^76S*%V;X{*eNz zp)tN7#jr@3g2_{%aVeoCpc0bfwg}BwEyCD{R*NtRlD_VyrIfSOyCXzv}nMiX2)~0Vc z!*5aq{YRPnKI5ffe)2BLS=5dQ#pD7Kv6`dhHN>zC8W>d*ugO9cz^3g3Oq}3j{~XLv z)p6O>4Zi`0QQjDaPH$qg6(PgKm(@lJuL4HUgE9xJH`_2nWkPI9ew{?@sEimZ1+|s1 z%&oogbrT_DDwpwx`ub7c>z~+)-vkxhQW$)k<=heFTeBqoG>e3MAhi>geSoXEd`bdE zN(&-%Y`UjpMDviW^TwjlxUX(zuiO<~n(>$%*hcY~S718{xP}YiCm?6MFSQql!7KyL z(lp132;(sYZtA+Tm1eS$GWTW}*#W;z${t86R$+PhECyn^y%`&n%A$~H)v?Rx_@;o<&A9tWv+vu zi8!>a^|Vq5`!lE{#ehkaIm*JaLir&mv)Puo&^lwj-t&lCJ;F9t5pDFUCiN{EKeg}! zOwJvn!q%EYKR~39QxrFRRZ0$!Uwgmc**Ie|{d0z)XV<8+m6C+0>Z~Um(MA|`d~G@| zN(~AJsaqyL1*7lf5j99kTz>UUkQ+pwI*7Rn3-bHmw6Uw>f1ZS?`2WEa_BEU)=)7Ki)RI@V}DPLotP z8}SB{NOLyk`_@-v$UMqeV#`qJ!4k^au{f#$)nC0KAW<;G6>)?)d;kl076;hsE9JdDFuciMM^gplHt?GYWud|c? z+bApazjdt9WLsSNg6vz1C~rPsI^BAmaHqKaDP8g$d*^-6bH|}`)9ZAjb7v5A!+r=WG3uo^2h08Jgb%5-~On+gfeeG2uq>h&VNL zLTg9?i6v+ANJE%(<|{`AGWlEOm$IHph}xN#+%%_4&?oT+qI4GBV2CqTyuX4x&lq+? z-X*6IvB){bIwCyI6nQ}_#OO~9(Ize$jY}R93rby>gulE$D982A6RK-tHvvc{)Ta-Z z=I1zwZlFB!iBN)Lu*%0N@$HyD&)?Gov6x2ckuag2WKaYlMbAWtz%-;Z2W$Psr{ zcA>{Vz%AFsaT)9SrKXvUK3SAIZg~@vpX2?)6ksT2BMHSe&VV@PxgbD6I*n-+*Wc$< z9+IaOMipz_-eW*QdgwKwP2)I7Ve)1f6Sq;p?u$%<$tm8^f__tulRP3k zp&d+7mlz9C(jmlZ#j4=M0$; zD)GaQm;PFJ-!{q$``>B?EzkZ6Mh}hMD6*(sanl~x zRuZ>fQZKz-lH)^5l+8vKRZ)uLw)wI?^ppAv1u*+Uin85w<+(Q&hcg%qfB`U=t!_P` z^}hY=@lU^nTmY!S_$0S5n@&r1H! zqQ%WLx{aSb`~jdV_}{Vk-{^$xXTf*j$^SV2ce5;BWY7Np{Et4Uo15d&u-yoI-A33N z_F7@@YFLlD<7TfLH~uyH9}wyMU;lrPXC?n5R1nV|^%Uy=u-)!-x{CizNDrHhM)Uvr z|9d=t|Lfnjw}W8!O9W&Xe4VB9MLe$!vyJWT4g9b-kE2CA3a;*h{pd?F3Vt39KL_bF zX!L^P^h?mFhdq`to!!rq>zf571@GZ!@HQF6lVovU4GyNmngF?yuokc_VbC?X{X%<(5U&r$-!Fp=-8WlT>W6Br}hw1Gsn%*bV>tLKrpv=ME;P`A1 zr1Rirv6#Ky-oCrLt3?E`md>xYCk$w|&2zp&pf`)#$;QSqLogRpz;ZCXPNwmWku*vc z>0Bh8-DivV)_kiSoLC8a>0}ZQ7l3Dj@_aquRn)N75(4wdx+7*A5b>ixlov&(maCS~5&jufMPj}Cuat0y~1~hIF9PR$*;OOG$^5P6|{`m<40u;`nWTV~LDQfWG z=)?JMFMrrQJw7;ocX>Ye4Hl{#r_-1>R`BKgWdG!Ku*_lraUFjxfcg7RK<&Mgqocv` z{$T&|;`jh+;DkH_=+pR4=0v{pr-GfQ)~JPzaagIk$)P{F?oIA{Q+wXjt~a&gO>KKq zTi(>BH#Mhq-qiZI;iQJOzAu&9=B9SNsU2@>+nd_*rZ&B)4R31bO?BJWt+i?)HN#C- z?fAB{k=F(H6Vg4={Qf6QzN%c#ej2>LINCivIoQ8EKe>E=@b=*H7bgeD=aIJGRxo#{WZTF#^XhB0Jh*OS%+u> z*(mXSG#ycTGp_*r3##-s9wngdoMMgKVjt$|*W}hyQ|Kvjm@F2P*n``LWcvBOnOnj@ z&MDW(Ehn*a%J{H5N=73ucI-nlr$_;M>~kZppu*2BbBcIS8{8vg@zeeOHchej$=^l}30<$r&2gCC z#q-_yt%5U;;Wa1YVSFtz!cRBT*-g5ffG5W?sdqQ$c^ab*5WjyOWu69J%w`61@Y9<~ zAjaPv)Q;ofXZTEi%`d0mo;n(br7D$^Tf`6ow_qc;pcDhQQ0NwN^$tr`iYLE}A4R2l z@=Hn_-BKPLUF}23uKIBc6(PyKd$4phkXy`$rqV&Gh*Cm%1@aNZuO9R)J>(Sepyp^I zma0@yZjpTK=(7hsTN}BBJP2}qB!9a(gho;?Mjlm#QJe!JOp z&15FHd4+BgFRpT;FH$?ntnk~P%|y^uP|Salj+FV0%A1~+14UUQOP)- z$I~JFN*580LD{GghQh)7$bb?e*CHfZ}nQg-)Z+-<1LM*+&6WB!jPuk@AaT;A0ahs&2GQd>cp?Y2E4-{ zrrxPHoA64t8Zenx>%s&e^;War3ZYaTfx^(D+w9gm4BIvgvwXJ@=SMT+(B76xOjeehAux0fod~s^<*)q2t0@rNy8weYrVT`UJKzCZrI?{yY z>hzjzw;tQ{<@bp-R}z-ZiRKIQ1GGI=}Hc@f&ZoqyF-|~PSR=CLta6@ z+iA6BCkea6btZ#hyVJ<4paik%J?JTI&UZk)E&Du*v20Yk)vb5)s#zsk4Zy#_TT+J_ zrEGOUmB^QVs~5Wba0gay4V@0KoS;HDvDX9AaauJyb--IlZ@=CJ6`5PZYGQQ&aHqi( zWZ3URuO~KOrJxCjikPbjuYHRr?$9l_Egg^_-j;5!-EHuuwCliuP&B0zhE^|;L%pZA zM`Bdy!Ufw24Gr5u4K_Q_l|zPmzu9QEg{G>5aSA(ilO}3p>F)sDez#TUJuC!S>ubv3`dFguL0Sw*|=!2-U-=OuHU9eNGOsWyDw}xh~1svnHr_lx}5pvP)b~{~38sO)acf_2BcLT}X zVp^vghD|Vz?03BZ($^Q<1o3IIzUq#l3yB`~sr&HXVMo%r+o-qHOW1Gvffo|J(*ac< zB9iR2*J*(|V^qhdL#mCDz1c($WXl=dKXvDE;{t9C%*6Nl!o-JRCsdwSt4*4XGJygD zs+Wx-IMuX}YZ4mJhH;c$x=<0Xzu9bHS1l8B@Kga9_l4O4msE;oz1{-_&#UNxK!G1o zB0}NT(CdTU=CThRD{P8Jgmn;CVfS0jb{802I-cRuNQc!t&!Y-YOOR zaI1iZbOpvZyyz;gt6rDJzuBw9~s9 zlCaZ-nSTzh*#rY6eXcGWTu~-;@W)%Ff-oM@>Ofa$3!;Qw=0`9J_1k?x#%{j{y>Mm3 z#)8iUKkRZ;>kY7KYFN@CnI`E2MF`v|8Q}4W74TW`9OP88JZyrQY0Kf}?I!LA$w z*N4v3YxJe7)#_=k7F9r=R*Ni#3p&TuVxCr`+mxObs5i~i5`)4n2v*N0lm(s^bFNsY z62Fyi)oxHl{C6`Cc8<+weijh7(P>IQ3tWeGU-?;$hO+q3D;hpd7I<3ZXhGVqMz14D;|z;c1TY8n5QaX|&uaEHKdaN_tZaqoPkZ1N_*u-gYLO=4zZ*^ESrM)H z&qgZ;bOFTyIUI-}6nX`9*o1zlIawX)+O`|E-BJNcSH6LlAa0~{L(-D%9uLI9VuCKf zYN|+F51n2MGU5HyQ9d&+sv@4Z(QJmA7#A`J*>XHizQ!stO3P)^aR8a(=_rB)HN^`% z4hQcpk9I$Nz{MhG7jNGl{AN(Jq(gB?rKx_R(wHhy?<9<(UBwvfo*u1(k?KM!O^B$4 zrIUtQsU%kKcaQhiLCf;H?GL6Aaz88Up*~susr$tQ>VEe^H5@tjiv`vBo(EMqJZ`!H z(fR6!r+fq7hg^u3F;>i`zcDOE3w{nW2&YSEhvMF849oIvW8lPyW)b-MJq7m+@SMb_ zAml3TINe{)V09i~aKyT({%tqA2Z)O~e4jvHS&;+ebVUvnT_+2M?=dkRsWj4h-o*Vl z8={VwE>6Z+Qhg>>#>!ZUdKm(uzT*(qE`xIvzBC;S!BwBZx#4Xv+jX2SPNwhX>2hj) zAT$UFWZ6rT=@3?GPBn<&Lol1iU!ck$rp1sn7nH*C&iP%E#T>$2GMNO~O?rn#@1pq>a(Pv= zLWjrPhuqLTFN-}1--K+;L@KFWxpT*)Fm zppPz=^J(y$30UnQJ6=vEC-cGWY;nIS3ADAtVSlrFg@Foy^UE!@fuz>{ehAj@CpwIu z!lLP9GMdMNFm4XL#YK{W?fX`kfni6z#*z(*F=C-3ZqY$0J9qNjCxbr?mRe%Q+E}(M zHeA(Mv>Nn=_uKPSz~Ma4R<0z~E3xQBxbuV}QFQSWYF1%5j$oDhNThSL3X2HnvI-?$ zveH7#P1eSN)pT}RJSH&*&fr)AFW7MPDyhFc)EfP9>aeJ+*YW!}aMfOYb@BAa3(=x;qK*7)DY}? znT$}B7z9A3M$-K5;$T0MdI{Z$P0Cq2jHlPo6`sEdLP3?>OmDz?>6uEAaDZ+ilJLVM zjxrdr6Jp>tvThbEQtmd^DvCDR^DT%${GO`TAfu5>*}C;NZv8w4)KDqA_z^8}lo|-lg&yB*4JTWr_{Q$%{noJf$$h<`xQ6r3Nd}D#2g=Vj}^H4*Uj`q(}2} z8ek=?f|5*i*l0A*K(!W46J}1&?`LuF+#=tu{Zv*)AHf9FCDReLx zt#f&Pbu~$cpN-NP2nM!6jm2qbH1$b6&o&Oa3~VEMw@Pm577!fx{|Y2W6GK@uW|@jN9tOGsDPfv09zlvIC`5?8 z>4LNxQ&EA!Q$3dOv0tx=n88c!w!@f$iB>@)M6+ze-6vj8)esdjX~FQB@n z<0cs=qAt63>RKNS4<7^Oe*lA+Rm^T;`QXT0|A;35_{$(AOJ~rAT=^mFuP0C9JZ1hq zAVs4rR-1);0wH*4CigG*lQ~)H`x;f5ZOWzrMnBUV`r2-&3Eh^`6bvYBCr5KL0mTbl zFdj$TU@cMt9n3gkf-!*vJzCrI;3~wGhFn>!<4hkw@$3-~iN|ebkSXi^ytUKtb)B-lL zVxB+t5Q2;j3W<4i9VJsW)_FiL&sS%p-wA6qj+eR{`D^tTW`(fLDgyA5kD*;fhP_W1 z0INQ9fh1n8zh-U^V@HO;JPx`gbb3oPRk`S=P~)r`4`5*mz-RjchqJuGLrNkni6NfP z#9^lG2pZ)@@Z|Yn5?0NU9N_z)!OoLg7O!DV{9&H3G_He?uISdtbT=sC0%VOU4N<4C zf@|}{hvQGZ6%{GFlngw|!M&X>{4!Frg@mX5tWqse({I`S&*K#T-6KO@WG4jK;eZ+L3$QY> zKpEXos8PLMpQ^S_vzx!=>y_LwW3Gt(*rnvFkGFw?!nRv0EavDiJ<$RjQ_%}p3*R^r` zQ3Z0#4)Gw5XO;H@0YnO}miBPdVVIg5kE3nn-DUeDPGB+aRkqn+M?q}rg z;oxJ4zbL?od+Q;nc@sd61l0n{@i5LZ2_mn~r=3r+pQ6c!)pHLf+lm z_(GLS|6OP>EJx~`Rq<3V#XKgbAe9R8K|V%~Uny`0ys<@V`^cIzLMAWI9Rbgvw8Oc! z$royOwMaa~!TbiDR3#`=&!{As9stys&5%v+4J*#))1vEnOy*9S{8$-u)p7?#;is0f z_R7jDqpk~!W97?R_b0OI3@>HRA0*D=`Da-3a^m!@C>qIxK{<0O?3g7W#vl%Co`*?6 zgg!NW*1)I}I4MpkponQ%TnG%95&+98U}IU5S{0d&$J84asmYNNaZQq_eQJ*#!2BnL zyJY|P4+(eKTw}PyG8D#H$$YdXY;2W|#qf$gxKnsEN_~5FZc@CeM?W!&RT4q{&8Nz^ z%EA@1(L_vx5@skd`Y`5&n&KXbP@P=+E~n#xjU#Qf0dFod6S97H*+RB2LB0vz$%P9t z)fPXOY^eAKyd7fI;HCrpi73ZsXkmH85Iti)9ZLgcB&c$od64mjDsrpHA3 z7^ZOV#p%Y+D?3jy+iO<&@(l|E$hq6{Gq;5u`;67{yizqQl%31=%#fyPeP;eNp%Pu% zY7toTk}Id**ax;@0FvWu`eMN}jZ563xkSFi&>^oX!;TY|?|R|Vf`(|U&tkP&#BAJ<7X9OdQ*>c90K9Lc@-BhI9SfAAA+(?~@1ZjeGz?{vTRX-3^4jd=CX=o5#P2!U) z{LaY;E3g*m1OCKQ_@~yWKrGTa08dn-dR5Y;8k|f$aP}rCEaY9iIvp3H7C_iErxB$9 zR6X;HB2A)(>|7aD^0?TRrdIlSW996Njc3jj%Q`-$zQD}wvN1|P!D92dY6r<<6>-fhMVDZ0wv(BPBnAr%U4 zKExXrGH@i&0w(ZrM4=-9bq)K!*_JmxWOK=#v7p97{1%c4bX?HEup~#K_uOZrkgml( z%SwOc+eUt2*a#ZG4i3f?2#MzWfKacrWkg}j$k&QjgTlF$%8U&$VC^@Q2Jr%eAYpM~ zoFz2UK|rno+bOs6qLhDSnJ%$)O?FzJ3h-GeU`L?>f;P?hS{v3e(;4!*kPg&!hP^>~*VrBNGD<$dF!#|>5T?NF#dhC{?T;0KfCfp{dsiwO+x9@` z8Smaz%6bO2-nZuLzck9Zs~dljCSnU}(d7`o_f#c!ZhqSF$47SQFpWG3Ch7p1Ob{h9 zQrdXBUNNq&W+Luvxmm#!kpJOw5-rFLS1ihp2)V2}`;6h9bPCAe#_^25QVX02e@%S$ zEK1h_$>ssSb&$w4mt!(FW0-uciS486aVH5(dGd^z4RM1NV)x)N5~nxyYO6#yJ+Dv1 z(6@jX)iN$UtWukkCGbWN-C(v{kjhd^VhdGtIpxgYK1eUy8ab!2ik-fL+RKA9iKZ%m2m>zWi#NSOv;_h( zUr)*%k{F8c$q?JgF_g5^;xzu_GJ&De2NHQ&^EVwGY9Dr|Ll`xr2-nn@IkR~lpwAuM z<97E&^qH0+$pH-S8EDv)21uZ*vk1v>IY-#!@4(y&ZL5icn}|kQtdB5yQH7-m@LtG; zqZ8b`pO_RWUKPluTl%zETJum-B3mRKKYo*6<0EIgvb$);Vp9`13HKE&Ho(m|n-rwl zLJtG4N>u6Zlefthn9Xz!+kJo>Ss71-J1QmP-&QyBX`f<6_)7a)gN0c7>%IBbXW)RLI^=P>q$#7M!mI=&yMhaY&d6c6V zI&yliEs4>U~6uC36 z!Xei12}Nz`Sb_ub1#NYnWB7oHqdZD-h-WjYGbE|ZhJX1OpobhyRK0RiNHAZ1ff^MK z_SSLA#mAtOA!q!F3BJLnEG}9|e{)Bi`uSCqQ#0iy2B=g*9n7>U22t!jLzjm^Wd!{d z!T|D1t|fc<()3I80-tL7@mhZWtibCw2FFAYH8NHWQi!=v5o$WgbEsWHJ?@T1I%)>F z$~!jd*M?_|#sXaa_-+g8E^`N=M2n3Hcse@X*wm2Yc&0+hqvaQ{mtB? zaQwRET<8)Ot;Td>jjQ6WHSMM{*HrS(hVO6)hWA2NgN=a3jlcnCLW{x1@#}|_uS&VjRocRD1!;Wl{tBoAv?ffxZtF!;wE>t8rw3+ zO8Z(GJtL8&2@GkCnQ2z5ip^;+;=qr76g($d&@a|3kfF7rZrm*?v4Ynap$aSwiPX5W621J9_K@e zXS7tr!^0lfsfO4Q6sh2cI_z*FR`aZio7$Wf0%1M|VOJg@d6jE?3Sx>n(3)rmnKtbU zfLw!N>cv^Hn2VFFQQA@!{N7nPs|^vDj5(dkJ`mS5-sp~6u!$r6gbw|LKR?mfLD~5U zt1n+BqURO5)v`3HT?DY1Y?WBf!vv!^%*FDE7?W*P*;jsiQSe63w&VKcthUv@x`k13{(Qci{&T(V#P7DcQ-h~-elOR&>L#^T(6Vo-XarViY@!{ zX?2WOlEYtKlTWYi{$`KDS;3-lcW$!*d-4 zo%8+yN&fttTNP`fi!GB}mA>B81U_zAW5A+|#)HNz=B*G;%hnmZ*auD}8Sn;o7)*6x zV+!MHxlp;HKz-pSQQ^h9AhPtql2)%@HN-Ebygs_8A@4TUAg3Yu1cQmbiQJZ2#2YV++M}y=2!T#mN@xl3T#nHcT#^COZZpfg( z-cp0Tg+s7cp$|8|ymC*LztL7oHADD?0Y#fl4G=~fa*M&)T(yzqdEmqfJ{4YHR`V=5 zbdiC@JNy6${c`e$&g>8Z6i+bPv`9hpaQ<{KWjnvmUqL?stl%r#2}-Xc5KdUuK7CZ> z$|c1y?l`$#&KZX*r8o1cQ<_%Drn-3Lb3)wBocHxcwwh$S;dKr$P_P>x(d z*T=hR6vu8h_-XJ+@kNVm;l%Kb$e`1r%L&{wG7&PI@k6qCkl{u47%oyxHwh@m`S9kR zmKmyLu2NA_2-LZXiq^e8rg9~f8Cqczmw$#Bxp(!fBTi@*)QCbZEH=#Dhwt2Yf`#2Bl6sEf3HzZZo+@x6Cq6}XF1sesvfiUcdtx=Z$3iI*G4AQ9Ko{Z~@m-;7WJdxwuC2+b6^ouL64tWZ4yWF1EO^=TYdY zd#JqlStAREuAJWW<61$Ok3x#>zbe3rjb_$Gi=aLpFZ*h?0=_Z~%_4-QiJH-zCm|pW zRc!*U6CNl(s&~NK^Oo$;-B^o|$Y})hmWZbOH0c;mwG~^V`0??|uJEXx^SI+&3P5|- z%9dNfMj%Qx(V3rsqVmm+#OZ*od56_DQ3vffxNqL9Hs?U{ocSDW$07BG>DU<_W4y1>5=1c^y^j~XRtnAW`Cpm=T`uZtV1;SI*)gkVj#Gmq`|S2k?DeGYl{v>9Y7PDSZMaYK?(6X7wJ0sJbrI z#!f9=p>^Akk>vv#mW|mTvT_PR7d9>aeh~0eUa;tF(B}r`xDx2OS)Wi&c>v7vKl;%+ z<=3<&qCI)$q|7eWqNnl@bEKVz`rM(#KaCV1H~+4bc=9%;^M6y$Keb`AE@93Kn5mud zv0BCTTeUuowT074Io=38*rc^_BF?i#Ui<>I7v2x^{@}ye<-6093ml{#9AEx+V?7TD z2brZDZr^M<78Yra%dJEHl*$ZB;38P|OS!%iy4QuG@-zzxb&#Z-L1brex%Yl>c244QHu$i6O1sb2>`Uh8 z6-|jhpKw`KzFb!R6FMznncHjWYl&{_gG}wpg-l;dK-MR*&r`<3H>R3+#Tv1Op5Q?F zz&m9E@x}%t;j^Z!0Uw1zA&e6P*D$Mz*XR9Ym5?$1=RXF{>j3^w)OuCh2+AJq)XV7d zbQOcf@KsJ^cPeKB@>G>ux_&6NYxJEJ{do#i;v2=bE^z+wFu6?@uk$XAkbT@YNtV^v z#MsJ-V=*gswELTbql=@4#$&;SQ^$~`;(zWyq4XM7XWN!}sEMLJ{4v+3jhpxm4Hrb(8H9= zUafDF#ym2k{EBJ*rR-@&R<)(i77~cK<=^BA7S#WU6WH-la%Ll5cDqptgMrTqtvyX; z{m9SjyyaUPTJNhRItopufZ{s8%g$}nVXoy5a{UWFKGO8YuA?0)Ith5tbhOB$c*#>^(knR2X z>~uP1b>eQsjhxF#O>#hSn?C+s_Cyp;aa8u$QsBH<*tdP2NT!!W^0-CU+ApKeHfVU| z?6H^Zw6w)TYs3bvs8Wf^Y7OOAOp4oxzLHhBGEYDg;gZ?E>?n}u3_cn^h2;+P)?G()w%K!o=O!Vi6$z;?-bi9ZuyyNxpubm zrrTQkhJVZ39EsBR3|!%!m+ftKnu&fe1jcOH>0|8p7&^F_Rz&lf`92Z0&R_2L&Ptp~ z4b}0pB}`E4c(ajMtIXBEAY{ZF4lvC;?wu6U&KbzqC+v`1Xy4uI>0C>p(G@d7_c5vv zY|20NN3@u|tvvKcRcD<1!+F}+-}2lXV%G57-Rls&JM#SUP2NTUkyX3L698)mP_O9#LP@wH5NetZNh5m4_59TDwI*6^s&HeWAz2Mp zl6Q?WURY1DDOq@Ww)bfGyz2;ZuXCUoEY%WOQeN_)YZCL02bq^A`>&}}SC+av2?PWv z=};doGd@TI6pr*zI=NEXH1>#q?ldRmkSznlQ&(yqjao9Ie@vc@?U!2nKjY?_+jcnyX!1 zB$@IlMGxtku`)J}wwB)UWuM|Sz=Ybpm%`z%P>lZ8;8Y)PfjijN|HB;5mn2i^HbBU{ zw+RZ6hQ27V0;794xGlZo73$Rt$z}xWR2zOyb#GP} zDwV3H>C|X5=Wr{_y*>ft+4XuKqAAk)3`c={6rvD;IvjFUDxRS@tEP5HOVnT`M4ep# z&FRC&m{^=*bwj!pdZH=(d=4_eG6eNv`$aW)@$ut}66aRy+&hg&Omi^FA)W&h#r0em zqMq=r%)g5mgPvT zAS8oaKuAS^l}ADTfHo;kaI39mpMxPpBVm^x3x9}!Hdm1Rn*32Rg4rl)7|X^!^RU$afZdZ+};k$Wa?hxWF0ld(5l%6OvLf3)wKiFFS)L0#MeJ*7yyP`@rtj&Ry3TszjI0?9pKo$uTcA`$C zycY;%%g9}t!k-8PbxiSZ>+a)pt_o?icjIv-f_IW(iqrW_Q>xhNC1OiESMk&^B$eYU zimf!l?IfaNOXskh#iuhN#D9<-#tR6ATX^CI?k(Jn=SQEmihDl)KKz7}FE3udSjl;N zSisK9{t``KH*c_-R~loVf=f~jxJ+Re5y=cy=c;Up3-vR08}kSAr(!ux;K!J;0>f8LAuJE2RV|YY&@8N4yb1 zoyZ`^y4;|NBwsgq5{w=yBl`5#>gf;9P0;18tzJD3@_jpvMU*vW<$?|0%R(_~u>R)$5-9{SY7dcE82LS6LOf9uUo z^I6zzg{?Z|Y=w}&6^5N>LH*fxc$TQypVhxhUH^s;j?3TD5@B&#o@}6k6W*~bV{23)07JRW&_D5O`f$;WD#gsW@|NSQd0%xYvgVfO6* z&wuyxkM^#ww@ny`=NXCbz}vPearjTwhe_3%YJJ!yO`Y~kuxX>U0RdT?Z@;^<4TMBt zQZ%-%+)Dxm`|$m24&R;6b{)q_0$W55=V9pc_&nx862_rO;wX&flhX<2n8V}0q0abs zeILeuFd2Ye`S|aZ{{Z@*8~9!Q&v$}x{vU#l=zo3CFyuEfy+JOlttgEvsnhlAgrnm2 zuTYlL(q=?HyP=*k!LU6W$3z2%I$O4^TpDR5}$`Wa0BkS;xFlc zZsd>p-w@O*e|i&7PNJUq-}CkNKdOMCgWvz2H|l?b&`0prfOrEg&~s@Dj=u>r4Y>?p z>2(0pP`aUIGuJds<8xMlns##_g9>VPDwa!UcmX3!^&|vkZi$%BoG5kB9@Ea`qJjpY zx=zy!o4c(oG%*=rW4cDK!C#n$!z|J{X_MT-V(Ic(Uqmru=%=1hndD91`lghDQ^4a^ z+va%@-`&ZL7&shcGP)Lu$c2e&!XtH~b}YyWtb+2_=o09YjrATFYg~<~03OL@mUIcj zn%e9(JN>TcHW^4%RwB0?__yCM*}`-Q#Q$2QbOlo(b0E($Co_p=6z-L^tXFFHh}&(B zrmZ@F6Km8ak4wyl!z|PAnDrg{XOCY>sa8ih9cEEiwgWZYJzY<1l(=7aPfRv2L5K`-ZUl*5GpBAioKJin3q>)A%X`~lIzW`8ey1oDq0RUf$ B&65BC From 9cc1a7aaaa36838d1a22cfce097065987dfb1157 Mon Sep 17 00:00:00 2001 From: David Back Date: Wed, 6 Mar 2019 13:39:40 -0800 Subject: [PATCH 30/44] CR changes --- .../Assets/Editor/AvatarExporter.cs | 22 ++---------------- .../avatarExporter.unitypackage | Bin 15949 -> 15720 bytes 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter.cs b/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter.cs index 40994c8f46..f8728f9e7e 100644 --- a/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter.cs +++ b/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter.cs @@ -274,7 +274,6 @@ class AvatarExporter : MonoBehaviour { public double roughness; public string roughnessMap; public string normalMap; - public string heightMap; public string occlusionMap; public Color emissive; public string emissiveMap; @@ -296,9 +295,6 @@ class AvatarExporter : MonoBehaviour { if (!string.IsNullOrEmpty(normalMap)) { json += "\"normalMap\": \"" + normalMap + "\", "; } - if (!string.IsNullOrEmpty(heightMap)) { - json += "\"heightMap\": \"" + heightMap + "\", "; - } if (!string.IsNullOrEmpty(occlusionMap)) { json += "\"occlusionMap\": \"" + occlusionMap + "\", "; } @@ -326,7 +322,6 @@ class AvatarExporter : MonoBehaviour { static Dictionary materialDatas = new Dictionary(); static List materialAlternateStandardShader = new List(); static Dictionary materialUnsupportedShader = new Dictionary(); - static List normalMapAndHeightMapNotBoth = new List(); [MenuItem("High Fidelity/Export New Avatar")] static void ExportNewAvatar() { @@ -396,9 +391,6 @@ class AvatarExporter : MonoBehaviour { warnings += "The material " + material.Key + " is using an unsupported shader " + material.Value + ". Please change it to a Standard shader type.\n\n"; } - foreach (string materialName in normalMapAndHeightMapNotBoth) { - warnings += "The material " + materialName + " has both a normal map and a height map assigned but can only use 1.\n\n"; - } warnings += textureWarnings; if (!string.IsNullOrEmpty(boneErrors)) { // if there are both errors and warnings then warnings will be displayed with errors in the error dialog @@ -664,7 +656,7 @@ class AvatarExporter : MonoBehaviour { materialMappings[materialName] == DEFAULT_MATERIAL_NAME) { materialJson += "\"all\": "; } else { - materialJson += "\"[mat::" + materialName + "]\": "; + materialJson += "\"mat::" + materialName + "\": "; } materialJson += materialData.Value.getJSON(); materialJson += ", "; @@ -688,7 +680,6 @@ class AvatarExporter : MonoBehaviour { materialDatas.Clear(); materialAlternateStandardShader.Clear(); materialUnsupportedShader.Clear(); - normalMapAndHeightMapNotBoth.Clear(); SetMaterialMappings(); @@ -1057,8 +1048,6 @@ class AvatarExporter : MonoBehaviour { string materialName = material.name; string shaderName = material.shader.name; - Debug.Log("material1 " + materialName); - // don't store any material data for unsupported shader types if (Array.IndexOf(SUPPORTED_SHADERS, shaderName) == -1) { if (!materialUnsupportedShader.ContainsKey(materialName)) { @@ -1073,7 +1062,6 @@ class AvatarExporter : MonoBehaviour { materialData.roughness = material.GetFloat("_Glossiness"); materialData.roughnessMap = GetMaterialTexture(material, "_SpecGlossMap"); materialData.normalMap = GetMaterialTexture(material, "_BumpMap"); - materialData.heightMap = GetMaterialTexture(material, "_ParallaxMap"); materialData.occlusionMap = GetMaterialTexture(material, "_OcclusionMap"); materialData.emissive = material.GetColor("_EmissionColor"); materialData.emissiveMap = GetMaterialTexture(material, "_EmissionMap"); @@ -1095,12 +1083,7 @@ class AvatarExporter : MonoBehaviour { } materialData.roughness = 1.0f - materialData.roughness; } - - // materials can not have both a normal map and a height map set - if (!string.IsNullOrEmpty(materialData.normalMap) && !string.IsNullOrEmpty(materialData.heightMap) && !normalMapAndHeightMapNotBoth.Contains(materialName)) { - normalMapAndHeightMapNotBoth.Add(materialName); - } - + // remap the material name from the Unity material name to the fbx material name that it overrides if (materialMappings.ContainsKey(materialName)) { materialName = materialMappings[materialName]; @@ -1137,7 +1120,6 @@ class AvatarExporter : MonoBehaviour { var material = mapping.Value as UnityEngine.Material; if (material != null) { materialMappings.Add(material.name, mapping.Key.name); - //Debug.Log("materialMapping " + material.name + " " + mapping.Key.name); } } } diff --git a/tools/unity-avatar-exporter/avatarExporter.unitypackage b/tools/unity-avatar-exporter/avatarExporter.unitypackage index ab39e1ed8f7d25ceb210c8ee59897c88aae20abb..aada1d3515d3ee1a165a97e0eee41c92a058e6b0 100644 GIT binary patch literal 15720 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 literal 15949 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 Date: Wed, 6 Mar 2019 14:02:58 -0800 Subject: [PATCH 31/44] Remove alternate versions of AnimPose(mat4) constructor --- libraries/animation/src/AnimPose.cpp | 36 ---------------------------- 1 file changed, 36 deletions(-) diff --git a/libraries/animation/src/AnimPose.cpp b/libraries/animation/src/AnimPose.cpp index 8b030fac39..56692e763e 100644 --- a/libraries/animation/src/AnimPose.cpp +++ b/libraries/animation/src/AnimPose.cpp @@ -11,9 +11,7 @@ #include "AnimPose.h" #include #include -#include #include "AnimUtil.h" -#include const AnimPose AnimPose::identity = AnimPose(glm::vec3(1.0f), glm::quat(), @@ -22,39 +20,6 @@ const AnimPose AnimPose::identity = AnimPose(glm::vec3(1.0f), #define NEW_VERSION AnimPose::AnimPose(const glm::mat4& mat) { -#if defined(ORIGINAL_VERSION) - static const float EPSILON = 0.0001f; - _scale = extractScale(mat); - // quat_cast doesn't work so well with scaled matrices, so cancel it out. - glm::mat4 tmp = glm::scale(mat, 1.0f / _scale); - _rot = glm::quat_cast(tmp); - float lengthSquared = glm::length2(_rot); - if (glm::abs(lengthSquared - 1.0f) > EPSILON) { - float oneOverLength = 1.0f / sqrtf(lengthSquared); - _rot = glm::quat(_rot.w * oneOverLength, _rot.x * oneOverLength, _rot.y * oneOverLength, _rot.z * oneOverLength); - } - _trans = extractTranslation(mat); -#elif defined(DECOMPOSE_VERSION) - // glm::decompose code - glm::vec3 scale; - glm::quat rotation; - glm::vec3 translation; - glm::vec3 skew; - glm::vec4 perspective; - bool result = glm::decompose(mat, scale, rotation, translation, skew, perspective); - _scale = scale; - _rot = rotation; - _trans = translation; - if (!result) { - // hack - const float HACK_FACTOR = 1000.0f; - glm::mat4 tmp = glm::scale(mat, HACK_FACTOR); - glm::decompose(tmp, scale, rotation, translation, skew, perspective); - _scale = scale / HACK_FACTOR; - _rot = rotation; - _trans = translation; - } -#elif defined(NEW_VERSION) glm::mat3 m(mat); _scale = glm::vec3(glm::length(m[0]), glm::length(m[1]), glm::length(m[2])); float det = glm::determinant(m); @@ -79,7 +44,6 @@ AnimPose::AnimPose(const glm::mat4& mat) { } _trans = extractTranslation(mat); -#endif } glm::vec3 AnimPose::operator*(const glm::vec3& rhs) const { From c5e9a7d1ab2bdacd79602aa7354723370fa616ca Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Wed, 6 Mar 2019 14:26:50 -0800 Subject: [PATCH 32/44] Added unit test for AnimPose() ctor using matrix with negative determinant --- tests/animation/src/AnimTests.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/animation/src/AnimTests.cpp b/tests/animation/src/AnimTests.cpp index 0cd9571e22..a14ffcf967 100644 --- a/tests/animation/src/AnimTests.cpp +++ b/tests/animation/src/AnimTests.cpp @@ -443,6 +443,28 @@ void AnimTests::testAnimPose() { } } } + + + // test matrix that has a negative determiant. + glm::vec4 col0(-9.91782e-05f, -5.40349e-05f, 0.000724383f, 0.0f); + glm::vec4 col1(-0.000155237f, 0.00071579f, 3.21398e-05f, 0.0f); + glm::vec4 col2(0.000709614f, 0.000149036f, 0.000108273f, 0.0f); + glm::vec4 col3(0.117922f, 0.250457f, 0.102155f, 1.0f); + glm::mat4 m(col0, col1, col2, col3); + AnimPose p(m); + + glm::vec3 resultTrans = glm::vec3(col3); + glm::quat resultRot = glm::quat(0.0530394f, 0.751549f, 0.0949531f, -0.650649f); + glm::vec3 resultScale = glm::vec3(-0.000733135f, -0.000733135f, -0.000733135f); + + const float TEST_EPSILON2 = 0.00001f; + QCOMPARE_WITH_ABS_ERROR(p.trans(), resultTrans, TEST_EPSILON2); + + if (glm::dot(p.rot(), resultRot) < 0.0f) { + resultRot = -resultRot; + } + QCOMPARE_WITH_ABS_ERROR(p.rot(), resultRot, TEST_EPSILON2); + QCOMPARE_WITH_ABS_ERROR(p.scale(), resultScale, TEST_EPSILON2); } void AnimTests::testExpressionTokenizer() { From 0f3e1b91574c1f75fcab5e40f3aa21bc3a524ba1 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 6 Mar 2019 14:53:21 -0800 Subject: [PATCH 33/44] fix wearable scale on position change --- libraries/entities/src/EntityItem.cpp | 2 +- libraries/entities/src/EntityItemProperties.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 5da1c05aa2..df9f12afb9 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1868,7 +1868,7 @@ void EntityItem::setParentID(const QUuid& value) { glm::vec3 EntityItem::getScaledDimensions() const { glm::vec3 scale = getSNScale(); - return _unscaledDimensions * scale; + return getUnscaledDimensions() * scale; } void EntityItem::setScaledDimensions(const glm::vec3& value) { diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 5ae9b30869..ce5b8b558c 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -4177,7 +4177,7 @@ void EntityItemProperties::copySimulationRestrictedProperties(const EntityItemPo setAcceleration(entity->getAcceleration()); } if (!_localDimensionsChanged && !_dimensionsChanged) { - setDimensions(entity->getScaledDimensions()); + setLocalDimensions(entity->getScaledDimensions()); } } From 96eb137df26917155625d9fa223b18e8a5cea03e Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 6 Mar 2019 15:53:25 -0800 Subject: [PATCH 34/44] fix debugAvatarMixer.js --- interface/src/ui/overlays/Overlays.cpp | 3 ++- .../developer/debugging/debugAvatarMixer.js | 19 ++++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index dfd698f6c5..c776cffd67 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -204,7 +204,8 @@ QString Overlays::overlayToEntityType(const QString& type) { #define RENAME_PROP(o, e) \ { \ auto iter = overlayProps.find(#o); \ - if (iter != overlayProps.end()) { \ + if (iter != overlayProps.end() && \ + !overlayProps.contains(#e)) { \ overlayProps[#e] = iter.value(); \ } \ } diff --git a/scripts/developer/debugging/debugAvatarMixer.js b/scripts/developer/debugging/debugAvatarMixer.js index 90f2de13a9..fad4283f7c 100644 --- a/scripts/developer/debugging/debugAvatarMixer.js +++ b/scripts/developer/debugging/debugAvatarMixer.js @@ -19,6 +19,11 @@ Script.include("/~/system/libraries/controllers.js"); var isShowingOverlays = true; var debugOverlays = {}; +var textSizeOverlay = Overlays.addOverlay("text3d", { + position: MyAvatar.position, + lineHeight: 0.1, + visible: false +}); function removeOverlays() { // enumerate the overlays and remove them @@ -31,6 +36,8 @@ function removeOverlays() { } } + Overlays.deleteOverlay(textSizeOverlay); + debugOverlays = {}; } @@ -60,8 +67,6 @@ function updateOverlays() { var overlayPosition = avatar.getJointPosition("Head"); overlayPosition.y += 1.15; - var rows = 8; - var text = avatarID + "\n" +"--- Data from Mixer ---\n" +"All: " + AvatarManager.getAvatarDataRate(avatarID).toFixed(2) + "kbps (" + AvatarManager.getAvatarUpdateRate(avatarID).toFixed(2) + "hz)" + "\n" @@ -85,9 +90,11 @@ function updateOverlays() { //+" SM: " + AvatarManager.getAvatarSimulationRate(avatarID,"skeletonModel").toFixed(2) + "hz \n" +" JD: " + AvatarManager.getAvatarSimulationRate(avatarID,"jointData").toFixed(2) + "hz \n" + var dimensions = Overlays.textSize(textSizeOverlay, text); if (avatarID in debugOverlays) { // keep the overlay above the current position of this avatar Overlays.editOverlay(debugOverlays[avatarID][0], { + dimensions: { x: 1.1 * dimensions.width, y: 0.6 * dimensions.height }, position: overlayPosition, text: text }); @@ -95,15 +102,9 @@ function updateOverlays() { // add the overlay above this avatar var newOverlay = Overlays.addOverlay("text3d", { position: overlayPosition, - dimensions: { - x: 1.25, - y: rows * 0.13 - }, + dimensions: { x: 1.1 * dimensions.width, y: 0.6 * dimensions.height }, lineHeight: 0.1, - font:{size:0.1}, text: text, - size: 1, - scale: 0.4, color: { red: 255, green: 255, blue: 255}, alpha: 1, solid: true, From a0bd2f67ec4f007fd3b944ce5b45d83bbd0cc6a2 Mon Sep 17 00:00:00 2001 From: danteruiz Date: Wed, 6 Mar 2019 17:20:36 -0800 Subject: [PATCH 35/44] fix stylus gizmo intersection --- interface/src/raypick/RayPick.cpp | 15 +++++++++++++++ interface/src/raypick/RayPick.h | 1 + interface/src/raypick/StylusPick.cpp | 24 +++++++++++++++++++++--- libraries/entities/src/ShapeEntityItem.h | 2 +- 4 files changed, 38 insertions(+), 4 deletions(-) diff --git a/interface/src/raypick/RayPick.cpp b/interface/src/raypick/RayPick.cpp index b030a67e17..8157c32a93 100644 --- a/interface/src/raypick/RayPick.cpp +++ b/interface/src/raypick/RayPick.cpp @@ -89,6 +89,8 @@ glm::vec3 RayPick::intersectRayWithEntityXYPlane(const QUuid& entityID, const gl return intersectRayWithXYPlane(origin, direction, props.getPosition(), props.getRotation(), props.getRegistrationPoint()); } + + glm::vec2 RayPick::projectOntoXYPlane(const glm::vec3& worldPos, const glm::vec3& position, const glm::quat& rotation, const glm::vec3& dimensions, const glm::vec3& registrationPoint, bool unNormalized) { glm::quat invRot = glm::inverse(rotation); glm::vec3 localPos = invRot * (worldPos - position); @@ -102,6 +104,19 @@ glm::vec2 RayPick::projectOntoXYPlane(const glm::vec3& worldPos, const glm::vec3 return pos2D; } +glm::vec2 RayPick::projectOntoXZPlane(const glm::vec3& worldPos, const glm::vec3& position, const glm::quat& rotation, const glm::vec3& dimensions, const glm::vec3& registrationPoint, bool unNormalized) { + glm::quat invRot = glm::inverse(rotation); + glm::vec3 localPos = invRot * (worldPos - position); + + glm::vec3 normalizedPos = (localPos / dimensions) + registrationPoint; + + glm::vec2 pos2D = glm::vec2(normalizedPos.x, (1.0f - normalizedPos.z)); + if (unNormalized) { + pos2D *= glm::vec2(dimensions.x, dimensions.z); + } + return pos2D; +} + glm::vec2 RayPick::projectOntoEntityXYPlane(const QUuid& entityID, const glm::vec3& worldPos, bool unNormalized) { EntityPropertyFlags desiredProperties; desiredProperties += PROP_POSITION; diff --git a/interface/src/raypick/RayPick.h b/interface/src/raypick/RayPick.h index 7625146408..161c930fef 100644 --- a/interface/src/raypick/RayPick.h +++ b/interface/src/raypick/RayPick.h @@ -86,6 +86,7 @@ public: static glm::vec2 projectOntoEntityXYPlane(const QUuid& entityID, const glm::vec3& worldPos, bool unNormalized = true); static glm::vec2 projectOntoXYPlane(const glm::vec3& worldPos, const glm::vec3& position, const glm::quat& rotation, const glm::vec3& dimensions, const glm::vec3& registrationPoint, bool unNormalized); + static glm::vec2 projectOntoXZPlane(const glm::vec3& worldPos, const glm::vec3& position, const glm::quat& rotation, const glm::vec3& dimensions, const glm::vec3& registrationPoint, bool unNoemalized); private: static glm::vec3 intersectRayWithXYPlane(const glm::vec3& origin, const glm::vec3& direction, const glm::vec3& point, const glm::quat& rotation, const glm::vec3& registration); diff --git a/interface/src/raypick/StylusPick.cpp b/interface/src/raypick/StylusPick.cpp index cf19b68a45..2bd371c506 100644 --- a/interface/src/raypick/StylusPick.cpp +++ b/interface/src/raypick/StylusPick.cpp @@ -155,15 +155,33 @@ PickResultPointer StylusPick::getEntityIntersection(const StylusTip& pick) { const auto entityRotation = entity->getWorldOrientation(); const auto entityPosition = entity->getWorldPosition(); + const auto entityType = entity->getType(); + glm::vec3 normal; - glm::vec3 normal = entityRotation * Vectors::UNIT_Z; + // TODO: Use the xz projection method for Sphere and Quad. + if (entityType == EntityTypes::Gizmo) { + normal = entityRotation * Vectors::UNIT_NEG_Y; + } else { + normal = entityRotation * Vectors::UNIT_Z; + } float distance = glm::dot(pick.position - entityPosition, normal); if (distance < nearestTarget.distance) { const auto entityDimensions = entity->getScaledDimensions(); const auto entityRegistrationPoint = entity->getRegistrationPoint(); glm::vec3 intersection = pick.position - (normal * distance); - glm::vec2 pos2D = RayPick::projectOntoXYPlane(intersection, entityPosition, entityRotation, - entityDimensions, entityRegistrationPoint, false); + glm::vec2 pos2D; + + + auto entityType = entity->getType(); + + if (entityType == EntityTypes::Gizmo) { + pos2D = RayPick::projectOntoXZPlane(intersection, entityPosition, entityRotation, + entityDimensions, entityRegistrationPoint, false); + } else { + pos2D = RayPick::projectOntoXYPlane(intersection, entityPosition, entityRotation, + entityDimensions, entityRegistrationPoint, false); + } + if (pos2D == glm::clamp(pos2D, glm::vec2(0), glm::vec2(1))) { IntersectionType type = IntersectionType::ENTITY; if (getFilter().doesPickLocalEntities()) { diff --git a/libraries/entities/src/ShapeEntityItem.h b/libraries/entities/src/ShapeEntityItem.h index 28edf2e1a2..363a7f39d1 100644 --- a/libraries/entities/src/ShapeEntityItem.h +++ b/libraries/entities/src/ShapeEntityItem.h @@ -85,7 +85,7 @@ public: void setUnscaledDimensions(const glm::vec3& value) override; bool shouldBePhysical() const override { return !isDead(); } - + bool supportsDetailedIntersection() const override; bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElementPointer& element, float& distance, From 380df059ffb62a8f723f18c4454af2b272bff3f7 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 6 Mar 2019 18:18:39 -0800 Subject: [PATCH 36/44] fix shapes app --- interface/src/avatar/MyAvatar.cpp | 3 +- interface/src/ui/overlays/Overlays.cpp | 29 +++++++++++++++---- .../src/RenderableModelEntityItem.cpp | 8 ++--- .../src/RenderableModelEntityItem.h | 2 +- .../src/RenderableZoneEntityItem.h | 2 +- libraries/entities/src/EntityItem.cpp | 4 +-- libraries/entities/src/EntityItem.h | 2 +- libraries/entities/src/EntityTree.cpp | 23 ++++++++++----- libraries/entities/src/LightEntityItem.cpp | 4 +-- libraries/entities/src/LightEntityItem.h | 2 +- libraries/shared/src/SpatiallyNestable.cpp | 10 ++++--- libraries/shared/src/SpatiallyNestable.h | 2 +- 12 files changed, 60 insertions(+), 31 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index faa9f88ae9..bfcb9269d5 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -910,7 +910,7 @@ void MyAvatar::simulate(float deltaTime, bool inView) { recorder->recordFrame(FRAME_TYPE, toFrame(*this)); } - locationChanged(); + locationChanged(true, false); // if a entity-child of this avatar has moved outside of its queryAACube, update the cube and tell the entity server. auto entityTreeRenderer = qApp->getEntities(); EntityTreePointer entityTree = entityTreeRenderer ? entityTreeRenderer->getTree() : nullptr; @@ -920,6 +920,7 @@ void MyAvatar::simulate(float deltaTime, bool inView) { zoneInteractionProperties = entityTreeRenderer->getZoneInteractionProperties(); EntityEditPacketSender* packetSender = qApp->getEntityEditPacketSender(); forEachDescendant([&](SpatiallyNestablePointer object) { + locationChanged(true, false); // we need to update attached queryAACubes in our own local tree so point-select always works // however we don't want to flood the update pipeline with AvatarEntity updates, so we assume // others have all info required to properly update queryAACube of AvatarEntities on their end diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index c776cffd67..1bcb040a77 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -494,15 +494,34 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove RENAME_PROP_CONVERT(p1, p1, [](const QVariant& v) { return vec3toVariant(glm::vec3(0.0f)); }); RENAME_PROP_CONVERT(p2, p2, [=](const QVariant& v) { glm::vec3 position; + bool hasPosition = false; + glm::quat rotation; + bool hasRotation = false; + auto iter2 = overlayProps.find("position"); if (iter2 != overlayProps.end()) { position = vec3FromVariant(iter2.value()); - } else if (!add) { - EntityPropertyFlags desiredProperties; - desiredProperties += PROP_POSITION; - position = DependencyManager::get()->getEntityProperties(id, desiredProperties).getPosition(); + hasPosition = true; } - return vec3toVariant(vec3FromVariant(v) - position); + iter2 = overlayProps.find("rotation"); + if (iter2 != overlayProps.end()) { + rotation = quatFromVariant(iter2.value()); + hasRotation = true; + } + + if (!add && !(hasPosition && hasRotation)) { + auto entity = DependencyManager::get()->getEntity(id); + if (entity) { + if (!hasPosition) { + position = entity->getWorldPosition(); + } + if (!hasRotation) { + rotation = entity->getWorldOrientation(); + } + } + } + + return vec3toVariant(glm::inverse(rotation) * (vec3FromVariant(v) - position)); }); RENAME_PROP(localStart, p1); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index e842d98714..03c50008a0 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -928,9 +928,9 @@ void RenderableModelEntityItem::setJointTranslationsSet(const QVector& tra _needsJointSimulation = true; } -void RenderableModelEntityItem::locationChanged(bool tellPhysics) { +void RenderableModelEntityItem::locationChanged(bool tellPhysics, bool tellChildren) { DETAILED_PERFORMANCE_TIMER("locationChanged"); - EntityItem::locationChanged(tellPhysics); + EntityItem::locationChanged(tellPhysics, tellChildren); auto model = getModel(); if (model && model->isLoaded()) { model->updateRenderItems(); @@ -1032,9 +1032,7 @@ void RenderableModelEntityItem::copyAnimationJointDataToModel() { }); if (changed) { - forEachChild([&](SpatiallyNestablePointer object) { - object->locationChanged(false); - }); + locationChanged(false, true); } } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 9adff9ca01..2fd1041c5f 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -108,7 +108,7 @@ public: virtual void setJointTranslations(const QVector& translations) override; virtual void setJointTranslationsSet(const QVector& translationsSet) override; - virtual void locationChanged(bool tellPhysics = true) override; + virtual void locationChanged(bool tellPhysics = true, bool tellChildren = true) override; virtual int getJointIndex(const QString& name) const override; virtual QStringList getJointNames() const override; diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.h b/libraries/entities-renderer/src/RenderableZoneEntityItem.h index 32b5cf94a0..2fa55f1540 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.h +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.h @@ -150,7 +150,7 @@ public: virtual bool addToScene(const EntityItemPointer& self, const render::ScenePointer& scene, render::Transaction& transaction) override; virtual void removeFromScene(const EntityItemPointer& self, const render::ScenePointer& scene, render::Transaction& transaction) override; private: - virtual void locationChanged(bool tellPhysics = true) override { EntityItem::locationChanged(tellPhysics); notifyBoundChanged(); } + virtual void locationChanged(bool tellPhysics = true, bool tellChildren = true) override { EntityItem::locationChanged(tellPhysics, tellChildren); notifyBoundChanged(); } virtual void dimensionsChanged() override { EntityItem::dimensionsChanged(); notifyBoundChanged(); } void notifyBoundChanged(); void notifyChangedRenderItem(); diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index d9614a0918..80db432fd0 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -2593,7 +2593,7 @@ QList EntityItem::getActionsOfType(EntityDynamicType typeT return result; } -void EntityItem::locationChanged(bool tellPhysics) { +void EntityItem::locationChanged(bool tellPhysics, bool tellChildren) { requiresRecalcBoxes(); if (tellPhysics) { _flags |= Simulation::DIRTY_TRANSFORM; @@ -2602,7 +2602,7 @@ void EntityItem::locationChanged(bool tellPhysics) { tree->entityChanged(getThisPointer()); } } - SpatiallyNestable::locationChanged(tellPhysics); // tell all the children, also + SpatiallyNestable::locationChanged(tellPhysics, tellChildren); std::pair data(_spaceIndex, glm::vec4(getWorldPosition(), _boundingRadius)); emit spaceUpdate(data); somethingChangedNotification(); diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 3fbfde6b24..f8c9c3b6f7 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -518,7 +518,7 @@ public: virtual bool getMeshes(MeshProxyList& result) { return true; } - virtual void locationChanged(bool tellPhysics = true) override; + virtual void locationChanged(bool tellPhysics = true, bool tellChildren = true) override; virtual bool getScalesWithParent() const override; diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index d4f15fa8b2..5234e77075 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -2039,6 +2039,8 @@ void EntityTree::fixupNeedsParentFixups() { Simulation::DIRTY_COLLISION_GROUP | Simulation::DIRTY_TRANSFORM); entityChanged(entity); + entity->locationChanged(true, false); + entity->forEachDescendant([&](SpatiallyNestablePointer object) { if (object->getNestableType() == NestableType::Entity) { EntityItemPointer descendantEntity = std::static_pointer_cast(object); @@ -2047,8 +2049,8 @@ void EntityTree::fixupNeedsParentFixups() { Simulation::DIRTY_TRANSFORM); entityChanged(descendantEntity); } + object->locationChanged(true, false); }); - entity->locationChanged(true); // Update our parent's bounding box bool success = false; @@ -3002,8 +3004,19 @@ void EntityTree::updateEntityQueryAACubeWorker(SpatiallyNestablePointer object, // if the queryBox has changed, tell the entity-server EntityItemPointer entity = std::dynamic_pointer_cast(object); if (entity) { - // NOTE: we rely on side-effects of the entity->updateQueryAACube() call in the following if() conditional: - if (entity->updateQueryAACube() || force) { + bool queryAACubeChanged = false; + if (!entity->hasChildren()) { + // updateQueryAACube will also update all ancestors' AACubes, so we only need to call this for leaf nodes + queryAACubeChanged = entity->updateQueryAACube(); + } else { + AACube oldCube = entity->getQueryAACube(); + object->forEachDescendant([&](SpatiallyNestablePointer descendant) { + updateEntityQueryAACubeWorker(descendant, packetSender, moveOperator, force, tellServer); + }); + queryAACubeChanged = oldCube != entity->getQueryAACube(); + } + + if (queryAACubeChanged || force) { bool success; AACube newCube = entity->getQueryAACube(success); if (success) { @@ -3027,10 +3040,6 @@ void EntityTree::updateEntityQueryAACubeWorker(SpatiallyNestablePointer object, entityChanged(entity); } } - - object->forEachDescendant([&](SpatiallyNestablePointer descendant) { - updateEntityQueryAACubeWorker(descendant, packetSender, moveOperator, force, tellServer); - }); } void EntityTree::updateEntityQueryAACube(SpatiallyNestablePointer object, EntityEditPacketSender* packetSender, diff --git a/libraries/entities/src/LightEntityItem.cpp b/libraries/entities/src/LightEntityItem.cpp index 88aae9691c..fcfda66319 100644 --- a/libraries/entities/src/LightEntityItem.cpp +++ b/libraries/entities/src/LightEntityItem.cpp @@ -55,8 +55,8 @@ void LightEntityItem::setUnscaledDimensions(const glm::vec3& value) { } } -void LightEntityItem::locationChanged(bool tellPhysics) { - EntityItem::locationChanged(tellPhysics); +void LightEntityItem::locationChanged(bool tellPhysics, bool tellChildren) { + EntityItem::locationChanged(tellPhysics, tellChildren); withWriteLock([&] { _lightPropertiesChanged = true; }); diff --git a/libraries/entities/src/LightEntityItem.h b/libraries/entities/src/LightEntityItem.h index 26b74f02cd..cc64121cb3 100644 --- a/libraries/entities/src/LightEntityItem.h +++ b/libraries/entities/src/LightEntityItem.h @@ -74,7 +74,7 @@ public: static bool getLightsArePickable() { return _lightsArePickable; } static void setLightsArePickable(bool value) { _lightsArePickable = value; } - virtual void locationChanged(bool tellPhysics) override; + virtual void locationChanged(bool tellPhysics, bool tellChildren) override; virtual void dimensionsChanged() override; bool lightPropertiesChanged() const { return _lightPropertiesChanged; } diff --git a/libraries/shared/src/SpatiallyNestable.cpp b/libraries/shared/src/SpatiallyNestable.cpp index d202afc59f..4d97f43e6a 100644 --- a/libraries/shared/src/SpatiallyNestable.cpp +++ b/libraries/shared/src/SpatiallyNestable.cpp @@ -1100,10 +1100,12 @@ void SpatiallyNestable::forEachDescendantTest(const ChildLambdaTest& actor) cons } } -void SpatiallyNestable::locationChanged(bool tellPhysics) { - forEachChild([&](SpatiallyNestablePointer object) { - object->locationChanged(tellPhysics); - }); +void SpatiallyNestable::locationChanged(bool tellPhysics, bool tellChildren) { + if (tellChildren) { + forEachChild([&](SpatiallyNestablePointer object) { + object->locationChanged(tellPhysics, tellChildren); + }); + } } AACube SpatiallyNestable::getMaximumAACube(bool& success) const { diff --git a/libraries/shared/src/SpatiallyNestable.h b/libraries/shared/src/SpatiallyNestable.h index 6b709f0352..f52dc4bf8b 100644 --- a/libraries/shared/src/SpatiallyNestable.h +++ b/libraries/shared/src/SpatiallyNestable.h @@ -211,7 +211,7 @@ public: void dump(const QString& prefix = "") const; - virtual void locationChanged(bool tellPhysics = true); // called when a this object's location has changed + virtual void locationChanged(bool tellPhysics = true, bool tellChildren = true); // called when a this object's location has changed virtual void dimensionsChanged() { _queryAACubeSet = false; } // called when a this object's dimensions have changed virtual void parentDeleted() { } // called on children of a deleted parent From dc4e2645da1439e193e3cbf88e346f4d524a3916 Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Thu, 7 Mar 2019 08:05:32 -0800 Subject: [PATCH 37/44] even better! --- libraries/entities/src/EntityTree.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 5234e77075..fffcd943c3 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -3010,7 +3010,7 @@ void EntityTree::updateEntityQueryAACubeWorker(SpatiallyNestablePointer object, queryAACubeChanged = entity->updateQueryAACube(); } else { AACube oldCube = entity->getQueryAACube(); - object->forEachDescendant([&](SpatiallyNestablePointer descendant) { + object->forEachChild([&](SpatiallyNestablePointer descendant) { updateEntityQueryAACubeWorker(descendant, packetSender, moveOperator, force, tellServer); }); queryAACubeChanged = oldCube != entity->getQueryAACube(); From 9ca38054999b581323d0c7da416e5d0a9d72007e Mon Sep 17 00:00:00 2001 From: danteruiz Date: Thu, 7 Mar 2019 10:27:16 -0800 Subject: [PATCH 38/44] making requested changes --- interface/src/raypick/StylusPick.cpp | 2 +- scripts/system/libraries/WebTablet.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/raypick/StylusPick.cpp b/interface/src/raypick/StylusPick.cpp index 2bd371c506..9139a16c6d 100644 --- a/interface/src/raypick/StylusPick.cpp +++ b/interface/src/raypick/StylusPick.cpp @@ -160,7 +160,7 @@ PickResultPointer StylusPick::getEntityIntersection(const StylusTip& pick) { // TODO: Use the xz projection method for Sphere and Quad. if (entityType == EntityTypes::Gizmo) { - normal = entityRotation * Vectors::UNIT_NEG_Y; + normal = entityRotation * Vectors::UNIT_Y; } else { normal = entityRotation * Vectors::UNIT_Z; } diff --git a/scripts/system/libraries/WebTablet.js b/scripts/system/libraries/WebTablet.js index c5ae9730f2..ceb7d8e77e 100644 --- a/scripts/system/libraries/WebTablet.js +++ b/scripts/system/libraries/WebTablet.js @@ -176,10 +176,10 @@ WebTablet = function (url, width, dpi, hand, location, visible) { this.homeButtonID = Overlays.addOverlay("circle3d", { name: "homeButton", localPosition: { x: HOME_BUTTON_X_OFFSET, y: HOME_BUTTON_Y_OFFSET, z: -HOME_BUTTON_Z_OFFSET }, - localRotation: { x: 0, y: 1, z: 0, w: 0}, + localRotation: Quat.fromVec3Degrees({ x: 180, y: 180, z: 0}), dimensions: { x: homeButtonDim, y: homeButtonDim, z: homeButtonDim }, solid: true, - alpha: 0.0, + alpha: 1.0, visible: visible, drawInFront: false, parentID: this.tabletEntityID, @@ -189,7 +189,7 @@ WebTablet = function (url, width, dpi, hand, location, visible) { this.homeButtonHighlightID = Overlays.addOverlay("circle3d", { name: "homeButtonHighlight", localPosition: { x: -HOME_BUTTON_X_OFFSET, y: HOME_BUTTON_Y_OFFSET, z: -HOME_BUTTON_Z_OFFSET }, - localRotation: { x: 0, y: 1, z: 0, w: 0}, + localRotation: { x: 0, y: -1, z: 0, w: 0}, dimensions: { x: homeButtonDim, y: homeButtonDim, z: homeButtonDim }, color: {red: 255, green: 255, blue: 255}, solid: true, From 05dc30a740270c176b51809b6d346415fd733710 Mon Sep 17 00:00:00 2001 From: danteruiz Date: Thu, 7 Mar 2019 10:48:47 -0800 Subject: [PATCH 39/44] more requested changes --- scripts/system/libraries/WebTablet.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/system/libraries/WebTablet.js b/scripts/system/libraries/WebTablet.js index ceb7d8e77e..9d333a1ae4 100644 --- a/scripts/system/libraries/WebTablet.js +++ b/scripts/system/libraries/WebTablet.js @@ -179,7 +179,7 @@ WebTablet = function (url, width, dpi, hand, location, visible) { localRotation: Quat.fromVec3Degrees({ x: 180, y: 180, z: 0}), dimensions: { x: homeButtonDim, y: homeButtonDim, z: homeButtonDim }, solid: true, - alpha: 1.0, + alpha: 0.0, visible: visible, drawInFront: false, parentID: this.tabletEntityID, @@ -189,7 +189,7 @@ WebTablet = function (url, width, dpi, hand, location, visible) { this.homeButtonHighlightID = Overlays.addOverlay("circle3d", { name: "homeButtonHighlight", localPosition: { x: -HOME_BUTTON_X_OFFSET, y: HOME_BUTTON_Y_OFFSET, z: -HOME_BUTTON_Z_OFFSET }, - localRotation: { x: 0, y: -1, z: 0, w: 0}, + localRotation: Quat.fromVec3Degrees({ x: 180, y: 180, z: 0}), dimensions: { x: homeButtonDim, y: homeButtonDim, z: homeButtonDim }, color: {red: 255, green: 255, blue: 255}, solid: true, From 87cfbe48d18d4fe5ca34f3c444a4e91984e7b3ef Mon Sep 17 00:00:00 2001 From: danteruiz Date: Thu, 7 Mar 2019 13:11:18 -0800 Subject: [PATCH 40/44] fix webSurfaceIntersection --- .../controllers/controllerModules/webSurfaceLaserInput.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/controllers/controllerModules/webSurfaceLaserInput.js b/scripts/system/controllers/controllerModules/webSurfaceLaserInput.js index 4f21b44533..cf700a8ad9 100644 --- a/scripts/system/controllers/controllerModules/webSurfaceLaserInput.js +++ b/scripts/system/controllers/controllerModules/webSurfaceLaserInput.js @@ -247,8 +247,8 @@ Script.include("/~/system/libraries/controllers.js"); this.run = function(controllerData, deltaTime) { this.addObjectToIgnoreList(controllerData); - var type = this.getInteractableType(controllerData, isTriggerPressed, false); var isTriggerPressed = controllerData.triggerValues[this.hand] > TRIGGER_OFF_VALUE; + var type = this.getInteractableType(controllerData, isTriggerPressed, false); var laserOn = isTriggerPressed || this.parameters.handLaser.alwaysOn; this.addObjectToIgnoreList(controllerData); From 0cf8f3e5c3d306545355ad3013e923cc9dca868f Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Thu, 7 Mar 2019 14:11:01 -0800 Subject: [PATCH 41/44] Code review feed back remove NEW_VERSION ifdef --- libraries/animation/src/AnimPose.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/animation/src/AnimPose.cpp b/libraries/animation/src/AnimPose.cpp index 56692e763e..8649db8233 100644 --- a/libraries/animation/src/AnimPose.cpp +++ b/libraries/animation/src/AnimPose.cpp @@ -17,8 +17,6 @@ const AnimPose AnimPose::identity = AnimPose(glm::vec3(1.0f), glm::quat(), glm::vec3(0.0f)); -#define NEW_VERSION - AnimPose::AnimPose(const glm::mat4& mat) { glm::mat3 m(mat); _scale = glm::vec3(glm::length(m[0]), glm::length(m[1]), glm::length(m[2])); From d1e376de0e15e4d4dda0aa6d0c81c43367352115 Mon Sep 17 00:00:00 2001 From: danteruiz Date: Thu, 7 Mar 2019 14:26:47 -0800 Subject: [PATCH 42/44] destroy modal dialogs that prevent interface from getting input --- .../resources/qml/dialogs/CustomQueryDialog.qml | 12 ++---------- interface/resources/qml/dialogs/FileDialog.qml | 2 +- interface/resources/qml/dialogs/QueryDialog.qml | 12 ++---------- 3 files changed, 5 insertions(+), 21 deletions(-) diff --git a/interface/resources/qml/dialogs/CustomQueryDialog.qml b/interface/resources/qml/dialogs/CustomQueryDialog.qml index 026068eee1..2497781db0 100644 --- a/interface/resources/qml/dialogs/CustomQueryDialog.qml +++ b/interface/resources/qml/dialogs/CustomQueryDialog.qml @@ -273,11 +273,7 @@ ModalWindow { onTriggered: { root.result = null; root.canceled(); - // FIXME we are leaking memory to avoid a crash - // root.destroy(); - - root.disableFade = true - visible = false; + root.destroy(); } } @@ -299,11 +295,7 @@ ModalWindow { } root.result = JSON.stringify(result); root.selected(root.result); - // FIXME we are leaking memory to avoid a crash - // root.destroy(); - - root.disableFade = true - visible = false; + root.destroy(); } } } diff --git a/interface/resources/qml/dialogs/FileDialog.qml b/interface/resources/qml/dialogs/FileDialog.qml index c1509e0fc1..ba5e162391 100644 --- a/interface/resources/qml/dialogs/FileDialog.qml +++ b/interface/resources/qml/dialogs/FileDialog.qml @@ -815,7 +815,7 @@ ModalWindow { Action { id: cancelAction text: "Cancel" - onTriggered: { canceled(); root.shown = false; } + onTriggered: { canceled(); root.destroy(); } } } diff --git a/interface/resources/qml/dialogs/QueryDialog.qml b/interface/resources/qml/dialogs/QueryDialog.qml index 9cfb3011bd..41ded7e934 100644 --- a/interface/resources/qml/dialogs/QueryDialog.qml +++ b/interface/resources/qml/dialogs/QueryDialog.qml @@ -168,11 +168,7 @@ ModalWindow { shortcut: "Esc" onTriggered: { root.canceled(); - // FIXME we are leaking memory to avoid a crash - // root.destroy(); - - root.disableFade = true - visible = false; + root.destroy(); } } @@ -183,11 +179,7 @@ ModalWindow { onTriggered: { root.result = items ? comboBox.currentText : textResult.text root.selected(root.result); - // FIXME we are leaking memory to avoid a crash - // root.destroy(); - - root.disableFade = true - visible = false; + root.destroy(); } } } From 1d6364773da9f193573697a47c1a523318871ace Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 7 Mar 2019 15:26:41 -0800 Subject: [PATCH 43/44] fix crash on startup --- libraries/model-baker/src/model-baker/ParseFlowDataTask.cpp | 3 ++- libraries/model-baker/src/model-baker/ParseFlowDataTask.h | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/libraries/model-baker/src/model-baker/ParseFlowDataTask.cpp b/libraries/model-baker/src/model-baker/ParseFlowDataTask.cpp index 6dff4f8c55..10991ecbe6 100644 --- a/libraries/model-baker/src/model-baker/ParseFlowDataTask.cpp +++ b/libraries/model-baker/src/model-baker/ParseFlowDataTask.cpp @@ -8,10 +8,11 @@ #include "ParseFlowDataTask.h" -void ParseFlowDataTask::run(const baker::BakeContextPointer& context, const Input& mapping, Output& output) { +void ParseFlowDataTask::run(const baker::BakeContextPointer& context, const Input& mappingPair, Output& output) { FlowData flowData; static const QString FLOW_PHYSICS_FIELD = "flowPhysicsData"; static const QString FLOW_COLLISIONS_FIELD = "flowCollisionsData"; + auto mapping = mappingPair.second; for (auto mappingIter = mapping.begin(); mappingIter != mapping.end(); mappingIter++) { if (mappingIter.key() == FLOW_PHYSICS_FIELD || mappingIter.key() == FLOW_COLLISIONS_FIELD) { QByteArray data = mappingIter.value().toByteArray(); diff --git a/libraries/model-baker/src/model-baker/ParseFlowDataTask.h b/libraries/model-baker/src/model-baker/ParseFlowDataTask.h index 7e1bc9fba1..65b8f7654b 100644 --- a/libraries/model-baker/src/model-baker/ParseFlowDataTask.h +++ b/libraries/model-baker/src/model-baker/ParseFlowDataTask.h @@ -12,9 +12,11 @@ #include #include "Engine.h" +#include "BakerTypes.h" + class ParseFlowDataTask { public: - using Input = QVariantHash; + using Input = baker::GeometryMappingPair; using Output = FlowData; using JobModel = baker::Job::ModelIO; From 0e1dbded229c5202806de742506c9b772d2d0046 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 7 Mar 2019 16:19:50 -0800 Subject: [PATCH 44/44] update avatar exporter package --- .../avatarExporter.unitypackage | Bin 15720 -> 15944 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/tools/unity-avatar-exporter/avatarExporter.unitypackage b/tools/unity-avatar-exporter/avatarExporter.unitypackage index aada1d3515d3ee1a165a97e0eee41c92a058e6b0..281cc80ddb4680277c4a84f68a44788bae88ba0d 100644 GIT binary patch literal 15944 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 literal 15720 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