{"action":"created","comment":{"url":"https://api.github.com/repos/highfidelity/hifi/pulls/comments/244219973","pull_request_review_id":188169779,"id":244219973,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDI0NDIxOTk3Mw==","diff_hunk":"@@ -70,138 +70,544 @@ public class AvatarExporter : MonoBehaviour {\n         {\"UpperChest\", \"Spine2\"},\n     };\n     \n-    public static string exportedPath = String.Empty;\n+    static readonly Dictionary<string, Quaternion> referenceAbsoluteRotations = new Dictionary<string, Quaternion> {\n+        {\"Head\", new Quaternion(-2.509889e-9f, -3.379446e-12f, 2.306033e-13f, 1f)},\n+        {\"Hips\", new Quaternion(-3.043941e-10f, -1.573706e-7f, 5.112975e-6f, 1f)},\n+        {\"LeftHandIndex3\", new Quaternion(-0.5086057f, 0.4908088f, -0.4912299f, -0.5090388f)},\n+        {\"LeftHandIndex2\", new Quaternion(-0.4934928f, 0.5062312f, -0.5064303f, -0.4936835f)},\n+        {\"LeftHandIndex1\", new Quaternion(-0.4986293f, 0.5017503f, -0.5013659f, -0.4982448f)},\n+        {\"LeftHandPinky3\", new Quaternion(-0.490056f, 0.5143053f, -0.5095307f, -0.4855038f)},\n+        {\"LeftHandPinky2\", new Quaternion(-0.5083722f, 0.4954255f, -0.4915887f, -0.5044324f)},\n+        {\"LeftHandPinky1\", new Quaternion(-0.5062528f, 0.497324f, -0.4937346f, -0.5025966f)},\n+        {\"LeftHandMiddle3\", new Quaternion(-0.4871885f, 0.5123404f, -0.5125002f, -0.4873383f)},\n+        {\"LeftHandMiddle2\", new Quaternion(-0.5171652f, 0.4827828f, -0.4822642f, -0.5166069f)},\n+        {\"LeftHandMiddle1\", new Quaternion(-0.4955998f, 0.5041052f, -0.5043675f, -0.4958555f)},\n+        {\"LeftHandRing3\", new Quaternion(-0.4936301f, 0.5097645f, -0.5061787f, -0.4901562f)},\n+        {\"LeftHandRing2\", new Quaternion(-0.5089865f, 0.4943658f, -0.4909532f, -0.5054707f)},\n+        {\"LeftHandRing1\", new Quaternion(-0.5020972f, 0.5005084f, -0.4979034f, -0.4994819f)},\n+        {\"LeftHandThumb3\", new Quaternion(-0.7228092f, 0.2988393f, -0.4472938f, -0.4337862f)},\n+        {\"LeftHandThumb2\", new Quaternion(-0.7554525f, 0.2018595f, -0.3871402f, -0.4885356f)},\n+        {\"LeftHandThumb1\", new Quaternion(-0.7276843f, 0.2878546f, -0.439926f, -0.4405459f)},\n+        {\"LeftEye\", new Quaternion(-2.509889e-9f, -3.379446e-12f, 2.306033e-13f, 1f)},\n+        {\"LeftFoot\", new Quaternion(0.009215056f, 0.3612514f, 0.9323555f, -0.01121602f)},\n+        {\"LeftHand\", new Quaternion(-0.4797408f, 0.5195366f, -0.5279632f, -0.4703038f)},\n+        {\"LeftForeArm\", new Quaternion(-0.4594738f, 0.4594729f, -0.5374805f, -0.5374788f)},\n+        {\"LeftLeg\", new Quaternion(-0.0005380471f, -0.03154583f, 0.9994993f, 0.002378627f)},\n+        {\"LeftShoulder\", new Quaternion(-0.3840606f, 0.525857f, -0.5957767f, -0.47013f)},\n+        {\"LeftToeBase\", new Quaternion(-0.0002536641f, 0.7113448f, 0.7027079f, -0.01379319f)},\n+        {\"LeftArm\", new Quaternion(-0.4591927f, 0.4591916f, -0.5377204f, -0.5377193f)},\n+        {\"LeftUpLeg\", new Quaternion(-0.0006682819f, 0.0006864658f, 0.9999968f, -0.002333928f)},\n+        {\"Neck\", new Quaternion(-2.509889e-9f, -3.379446e-12f, 2.306033e-13f, 1f)},\n+        {\"RightHandIndex3\", new Quaternion(0.5083892f, 0.4911618f, -0.4914584f, 0.5086939f)},\n+        {\"RightHandIndex2\", new Quaternion(0.4931984f, 0.5065879f, -0.5067145f, 0.4933202f)},\n+        {\"RightHandIndex1\", new Quaternion(0.4991491f, 0.5012957f, -0.5008481f, 0.4987026f)},\n+        {\"RightHandPinky3\", new Quaternion(0.4890696f, 0.5154139f, -0.5104482f, 0.4843578f)},\n+        {\"RightHandPinky2\", new Quaternion(0.5084175f, 0.495413f, -0.4915423f, 0.5044444f)},\n+        {\"RightHandPinky1\", new Quaternion(0.5069782f, 0.4965974f, -0.4930001f, 0.5033045f)},\n+        {\"RightHandMiddle3\", new Quaternion(0.4867662f, 0.5129694f, -0.5128888f, 0.4866894f)},\n+        {\"RightHandMiddle2\", new Quaternion(0.5167004f, 0.4833596f, -0.4827653f, 0.5160643f)},\n+        {\"RightHandMiddle1\", new Quaternion(0.4965845f, 0.5031784f, -0.5033959f, 0.4967981f)},\n+        {\"RightHandRing3\", new Quaternion(0.4933217f, 0.5102056f, -0.5064691f, 0.4897075f)},\n+        {\"RightHandRing2\", new Quaternion(0.5085972f, 0.494844f, -0.4913519f, 0.505007f)},\n+        {\"RightHandRing1\", new Quaternion(0.502959f, 0.4996676f, -0.4970418f, 0.5003144f)},\n+        {\"RightHandThumb3\", new Quaternion(0.7221864f, 0.3001843f, -0.4482129f, 0.4329457f)},\n+        {\"RightHandThumb2\", new Quaternion(0.755621f, 0.20102f, -0.386691f, 0.4889769f)},\n+        {\"RightHandThumb1\", new Quaternion(0.7277303f, 0.2876409f, -0.4398623f, 0.4406733f)},\n+        {\"RightEye\", new Quaternion(-2.509889e-9f, -3.379446e-12f, 2.306033e-13f, 1f)},\n+        {\"RightFoot\", new Quaternion(-0.009482829f, 0.3612484f, 0.9323512f, 0.01144584f)},\n+        {\"RightHand\", new Quaternion(0.4797273f, 0.5195542f, -0.5279628f, 0.4702987f)},\n+        {\"RightForeArm\", new Quaternion(0.4594217f, 0.4594215f, -0.5375242f, 0.5375237f)},\n+        {\"RightLeg\", new Quaternion(0.0005446263f, -0.03177159f, 0.9994922f, -0.002395923f)},\n+        {\"RightShoulder\", new Quaternion(0.3841222f, 0.5257177f, -0.5957286f, 0.4702966f)},\n+        {\"RightToeBase\", new Quaternion(0.0001034f, 0.7113398f, 0.7027067f, 0.01411251f)},\n+        {\"RightArm\", new Quaternion(0.4591419f, 0.4591423f, -0.537763f, 0.5377624f)},\n+        {\"RightUpLeg\", new Quaternion(0.0006750703f, 0.0008973633f, 0.9999966f, 0.002352045f)},\n+        {\"Spine\", new Quaternion(-0.05427956f, 1.508558e-7f, -2.775203e-6f, 0.9985258f)},\n+        {\"Spine1\", new Quaternion(-0.0824653f, 1.25274e-7f, -6.75759e-6f, 0.996594f)},\n+        {\"Spine2\", new Quaternion(-0.0824653f, 1.25274e-7f, -6.75759e-6f, 0.996594f)},\n+    };\n+\n+    static Dictionary<string, string> userBoneToHumanoidMappings = new Dictionary<string, string>();\n+    static Dictionary<string, string> userParentNames = new Dictionary<string, string>();\n+    static Dictionary<string, Quaternion> userAbsoluteRotations = new Dictionary<string, Quaternion>();\n+    \n+    static string assetPath = \"\";\n+    static string assetName = \"\";\n+    static HumanDescription humanDescription;\n  \n     [MenuItem(\"High Fidelity/Export New Avatar\")]\n-    public static void ExportNewAvatar() {\n+    static void ExportNewAvatar() {\n         ExportSelectedAvatar(false);\n     }\n-    \n-    [MenuItem(\"High Fidelity/Export New Avatar\", true)]\n-    private static bool ExportNewAvatarValidator() {\n-        // only enable Export New Avatar option if we have an asset selected\n-        string[] guids = Selection.assetGUIDs;\n-        return guids.Length > 0;\n-    }\n-     \n-    [MenuItem(\"High Fidelity/Update Avatar\")]\n-    public static void UpdateAvatar() {\n+\n+    [MenuItem(\"High Fidelity/Update Existing Avatar\")]\n+    static void UpdateAvatar() {\n         ExportSelectedAvatar(true);\n     }\n \n-    [MenuItem(\"High Fidelity/Update Avatar\", true)]\n-    private static bool UpdateAvatarValidation() {\n-        // only enable Update Avatar option if the selected avatar is the last one that was exported\n-        if (exportedPath != String.Empty) {\n-            string[] guids = Selection.assetGUIDs;\n-            if (guids.Length > 0) {\n-                string selectedAssetPath = AssetDatabase.GUIDToAssetPath(guids[0]);\n-                string selectedAsset = Path.GetFileNameWithoutExtension(selectedAssetPath);\n-                string exportedAsset = Path.GetFileNameWithoutExtension(exportedPath);\n-                return exportedAsset == selectedAsset;\n+    static void ExportSelectedAvatar(bool updateAvatar) {     \n+        string[] guids = Selection.assetGUIDs;\n+        if (guids.Length != 1) {\n+            if (guids.Length == 0) {\n+                EditorUtility.DisplayDialog(\"Error\", \"Please select an asset to export.\", \"Ok\");\n+            } else {\n+                EditorUtility.DisplayDialog(\"Error\", \"Please select a single asset to export.\", \"Ok\");\n             }\n+            return;\n         }\n-        return false;\n-    }\n-    \n-    public static void ExportSelectedAvatar(bool usePreviousPath) {     \n-        string assetPath = AssetDatabase.GUIDToAssetPath(Selection.assetGUIDs[0]);\n-        if (assetPath.LastIndexOf(\".fbx\") == -1) {\n-            EditorUtility.DisplayDialog(\"Error\", \"Please select an fbx avatar to export\", \"Ok\");\n+        assetPath = AssetDatabase.GUIDToAssetPath(Selection.assetGUIDs[0]);\n+        assetName = Path.GetFileNameWithoutExtension(assetPath);\n+        ModelImporter modelImporter = ModelImporter.GetAtPath(assetPath) as ModelImporter;\n+        if (assetPath.ToLower().LastIndexOf(\".fbx\") == -1 || modelImporter == null) {\n+            EditorUtility.DisplayDialog(\"Error\", \"Please select an .fbx model asset to export.\", \"Ok\");\n             return;\n         }\n-        ModelImporter importer = ModelImporter.GetAtPath(assetPath) as ModelImporter;\n-        if (importer == null) {\n-            EditorUtility.DisplayDialog(\"Error\", \"Please select a model\", \"Ok\");\n+        if (modelImporter.animationType != ModelImporterAnimationType.Human) {\n+            EditorUtility.DisplayDialog(\"Error\", \"Please set model's Animation Type to Humanoid in the Rig section of it's Inspector window.\", \"Ok\");\n             return;\n         }\n-        if (importer.animationType != ModelImporterAnimationType.Human) {\n-            EditorUtility.DisplayDialog(\"Error\", \"Please set model's Animation Type to Humanoid\", \"Ok\");\n+                \n+        humanDescription = modelImporter.humanDescription;   \n+        if (!SetJointMappingsAndParentNames()) {\n             return;\n         }\n+\n+        string documentsFolder = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments);\n+        string hifiFolder = documentsFolder + \"\\\\High Fidelity Projects\";\n+        if (updateAvatar) { // Update Existing Avatar menu option\n+            bool copyModelToExport = false;\n+            string initialPath = Directory.Exists(hifiFolder) ? hifiFolder : documentsFolder;\n+            \n+            // open file explorer defaulting to hifi projects folder in user documents to select target fst to update\n+            string exportFstPath = EditorUtility.OpenFilePanel(\"Select .fst to update\", initialPath, \"fst\");\n+            if (exportFstPath.Length == 0) { // file selection cancelled\n+                return;\n+            }\n+            exportFstPath = exportFstPath.Replace('/', '\\\\');\n+            \n+            // lookup the project name field from the fst file to update\n+            string projectName = \"\";\n+            try {\n+                string[] lines = File.ReadAllLines(exportFstPath);\n+                foreach (string line in lines) {\n+                    if (line.StartsWith(\"name\")) {\n+                        projectName = line.Substring(line.IndexOf(\"=\") + 2);\n+                        break;\n+                    }\n+                }\n+            } catch {\n+                EditorUtility.DisplayDialog(\"Error\", \"Failed to read from existing file \" + exportFstPath + \n+                                            \". Please check the file and try again.\", \"Ok\");\n+                return;\n+            }\n+            \n+            // delete existing fst file since we will write a new file\n+            // TODO: updating fst should only rewrite joint mappings and joint rotation offsets to existing file\n+            try {\n+                File.Delete(exportFstPath);\n+            } catch {\n+                EditorUtility.DisplayDialog(\"Error\", \"Failed to overwrite existing file \" + exportFstPath + \n+                                            \". Please check the file and try again.\", \"Ok\");\n+                return;\n+            }\n+            \n+            string exportModelPath = Path.GetDirectoryName(exportFstPath) + \"/\" + assetName + \".fbx\";\n+            if (File.Exists(exportModelPath)) { \n+                // if the fbx in Unity Assets is newer than the fbx in the target export\n+                // folder or vice-versa then ask to replace the older fbx with the newer fbx\n+                DateTime assetModelWriteTime = File.GetLastWriteTime(assetPath);\n+                DateTime targetModelWriteTime = File.GetLastWriteTime(exportModelPath);\n+                if (assetModelWriteTime > targetModelWriteTime) {\n+                    int option = EditorUtility.DisplayDialogComplex(\"Error\", \"The \" + assetName + \n+                                 \".fbx model in the Unity Assets folder is newer than the \" + exportModelPath + \n+                                 \" model.\\n\\nDo you want to replace the older .fbx with the newer .fbx?\",\n+                                 \"Yes\", \"No\", \"Cancel\");\n+                    if (option == 2) { // Cancel\n+                        return;\n+                    }\n+                    copyModelToExport = option == 0; // Yes\n+                } else if (assetModelWriteTime < targetModelWriteTime) {\n+                    int option = EditorUtility.DisplayDialogComplex(\"Error\", \"The \" + exportModelPath + \n+                                 \" model is newer than the \" + assetName + \".fbx model in the Unity Assets folder.\" +\n+                                 \"\\n\\nDo you want to replace the older .fbx with the newer .fbx and re-import it?\", \n+                                 \"Yes\", \"No\" , \"Cancel\");\n+                    if (option == 2) { // Cancel\n+                        return;\n+                    } else if (option == 0) { // Yes - copy model to Unity project\n+                        // delete existing fbx and associated meta file in Unity Assets\n+                        File.Delete(assetPath);\n+                        File.Delete(assetPath + \".meta\");","path":"tools/unity-avatar-exporter/Assets/Editor/AvatarExporter.cs","position":215,"original_position":215,"commit_id":"65cc683f800b44afbdf970c9e4af96d6d3ec7714","original_commit_id":"65cc683f800b44afbdf970c9e4af96d6d3ec7714","user":{"login":"dback2","id":31390055,"node_id":"MDQ6VXNlcjMxMzkwMDU1","avatar_url":"https://avatars3.githubusercontent.com/u/31390055?v=4","gravatar_id":"","url":"https://api.github.com/users/dback2","html_url":"https://github.com/dback2","followers_url":"https://api.github.com/users/dback2/followers","following_url":"https://api.github.com/users/dback2/following{/other_user}","gists_url":"https://api.github.com/users/dback2/gists{/gist_id}","starred_url":"https://api.github.com/users/dback2/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dback2/subscriptions","organizations_url":"https://api.github.com/users/dback2/orgs","repos_url":"https://api.github.com/users/dback2/repos","events_url":"https://api.github.com/users/dback2/events{/privacy}","received_events_url":"https://api.github.com/users/dback2/received_events","type":"User","site_admin":false},"body":"Will try it out, but in this case it was a careful balance to make this all work correctly with replacing the model asset and getting it re-imported and re-mapped in Humanoid before exporting.","created_at":"2018-12-27T20:21:21Z","updated_at":"2018-12-27T20:21:21Z","html_url":"https://github.com/highfidelity/hifi/pull/14583#discussion_r244219973","pull_request_url":"https://api.github.com/repos/highfidelity/hifi/pulls/14583","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/highfidelity/hifi/pulls/comments/244219973"},"html":{"href":"https://github.com/highfidelity/hifi/pull/14583#discussion_r244219973"},"pull_request":{"href":"https://api.github.com/repos/highfidelity/hifi/pulls/14583"}},"in_reply_to_id":244202523},"pull_request":{"url":"https://api.github.com/repos/highfidelity/hifi/pulls/14583","id":238843339,"node_id":"MDExOlB1bGxSZXF1ZXN0MjM4ODQzMzM5","html_url":"https://github.com/highfidelity/hifi/pull/14583","diff_url":"https://github.com/highfidelity/hifi/pull/14583.diff","patch_url":"https://github.com/highfidelity/hifi/pull/14583.patch","issue_url":"https://api.github.com/repos/highfidelity/hifi/issues/14583","number":14583,"state":"open","locked":false,"title":"Avatar Exporter - joint rotation offsets and file workflow changes","user":{"login":"dback2","id":31390055,"node_id":"MDQ6VXNlcjMxMzkwMDU1","avatar_url":"https://avatars3.githubusercontent.com/u/31390055?v=4","gravatar_id":"","url":"https://api.github.com/users/dback2","html_url":"https://github.com/dback2","followers_url":"https://api.github.com/users/dback2/followers","following_url":"https://api.github.com/users/dback2/following{/other_user}","gists_url":"https://api.github.com/users/dback2/gists{/gist_id}","starred_url":"https://api.github.com/users/dback2/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dback2/subscriptions","organizations_url":"https://api.github.com/users/dback2/orgs","repos_url":"https://api.github.com/users/dback2/repos","events_url":"https://api.github.com/users/dback2/events{/privacy}","received_events_url":"https://api.github.com/users/dback2/received_events","type":"User","site_admin":false},"body":"Functional spec under Description here:\r\nhttps://highfidelity.atlassian.net/wiki/spaces/Create/pages/419758221/Unity-+Hifi+Avatar+Export+Tool\r\n\r\nCompletes implementation for:\r\nhttps://highfidelity.manuscript.com/f/cases/19924/\r\n\r\nImport this package into your Unity project:\r\nhttps://github.com/highfidelity/hifi/raw/65cc683f800b44afbdf970c9e4af96d6d3ec7714/tools/unity-avatar-exporter/avatarExporter.unitypackage\r\n\r\nAnd choose High Fidelity menu -> Export New Avatar with your imported .fbx asset selected.\r\n\r\nThe exported fst can be used in any build starting with dev build 9729, you do not have to use the build from this PR as this Avatar Exporter is independent of Interface builds.\r\n\r\nTest Plan:\r\n\r\nNotes:\r\n- Post-Merge testing is not necessary as this PR will not affect the Interface build after merging\r\n- When testing the avatars in Interface, any avatar scale issues can be considered non-failures as scale is yet to be handled\r\n\r\nTest Steps:\r\n- Download the following files:\r\nhttps://github.com/highfidelity/hifi/raw/65cc683f800b44afbdf970c9e4af96d6d3ec7714/tools/unity-avatar-exporter/avatarExporter.unitypackage\r\nhttps://hifi-content.s3.amazonaws.com/davidback/avatars/zonneko.fbx\r\n- With Unity installed, open a new Unity project\r\n- Open the above avatarExporter.unitypackage and import it into your Unity project, and verify a High Fidelity menu appears as well as a README file in Assets window\r\n- Either select Assets -> Import New Asset and choose the zonneko.fbx you saved above, or drag the zonneko.fbx into the Assets window to import it\r\n- Verify with no asset selected if choosing High Fidelity menu > Export New Avatar that a dialog is displayed saying to please select an asset\r\n- Verify with more than 1 asset selected (such as zonneko and the README file) and choosing Export New Avatar that a dialog is displayed saying to please select a single asset\r\n- Select a different asset besides zonneko (such as the README file) and verify when choosing Export New Avatar that a dialog is displayed saying to please select an fbx model\r\n- Select zonneko and verify when choosing Export New Avatar that a dialog is displayed saying to please set Animation Type to Humanoid\r\n- Using the Animation Type dropdown in the Rig section of the Inspector on the right, set zonneko Animation Type to Humanoid and hit Apply\r\n- With zonneko still selected, verify a popup window is opened with Export project name and Export project location fields, the latter of which defaults to High Fidelity Projects folder in user's Documents folder (and High Fidelity Projects folder is created there at this time if it didn't already exist) \r\n- Verify if clicking Export with an empty Project name that red text displays saying to please define a project name\r\n- Verify if clicking Export with an empty Project location but not an empty Project name that red text displays saying to please define a project location\r\n- Verify if entering an invalid project location (such as not starting with a drive name) that red text displays saying project location is invalid. In certain cases this may not display until you hit Export, such as if you define an inaccessible drive.\r\n- Verify if clicking Browse that a folder explorer displays starting at the path from the Project location field, and that once choosing a new folder location and choosing Select Folder that the Project location field is populated with the new path\r\n- Choose a project name and location and Export the avatar\r\n- Verify after export that a File Explorer window opens to the project folder, which contains the zonneko.fbx, avatar.fst, and empty textures and scripts folders, and a warning dialog displays informing the user to ensure any external textures are copied over\r\n- Open the avatar.fst and verify there is a line \"jointMap = Spine2 = Chest\"\r\n- Change the project name you defined next to the name field at the top of the avatar.fst to anything else\r\n- Back in Unity, with the same avatar selected, choose High Fidelity menu -> Update Existing Avatar and select the avatar.fst you just modified in the file explorer that opens (the file explorer should default to the High Fidelity Projects folder again)\r\n- Verify a file explorer window then opens to the updated avatar location, and verify the project name next to the name field at the top of the avatar.fst stayed the same as the one you changed it to\r\n- Back in Unity, with the zonneko avatar selected, hit Configure in the Rig section of the Inspector panel\r\n- Delete the Hips bone and verify when exporting the avatar that an error is displayed saying there is no Hips bone\r\n- Undo the last bone deletion, and delete the Spine bone and verify when exporting the avatar that an error is displaying saying there is no Spine bone\r\n- Either upload the avatar.fst and zonneko.fbx you exported and updated above to an S3 bucket, or ask me to upload them for you\r\n- Use the uploaded avatar.fst in Interface and verify the avatar appears correct (besides being untextured) and perform different animations like movements and emotes to verify they look ok\r\n- Test exporting the following avatars (import to Unity, change animation type to Humanoid, and Export New Avatar) and verifying the successful ones in Interface, and request upload to S3 through me if needed\r\nhttps://hifi-content.s3.amazonaws.com/davidback/avatars/Hapineko.fbx (rig orientation incorrect, bones named incorrectly, and extra bones)\r\nhttps://hifi-content.s3.amazonaws.com/davidback/avatars/Mason_Idle.fbx (bones named incorrectly, not in t-pose, and extra bones)\r\nhttps://hifi-content.s3.amazonaws.com/davidback/avatars/fialka_rescale_cats.fbx (bones named incorrectly and extra bones)\r\nhttps://hifi-content.s3.amazonaws.com/davidback/avatars/engineer_original_names.fbx (bones named incorrectly and extra bones)\r\nhttps://hifi-content.s3.amazonaws.com/davidback/avatars/OgyariAnkou01.fbx (bones named incorrectly and extra bones)\r\nhttps://hifi-content.s3.amazonaws.com/davidback/avatars/MAN_1.fbx (extra bones)\r\nhttps://hifi-content.s3.amazonaws.com/davidback/avatars/drax-avatar.fbx (extra bones)\r\nhttps://hifi-content.s3.amazonaws.com/davidback/avatars/fbx-upload-test-pearl.fbx (extra bones)\r\nhttps://hifi-content.s3.amazonaws.com/davidback/avatars/CuteCreature.fbx (missing bones - will give an error on export that there is no Chest bone)\r\nhttps://hifi-content.s3.amazonaws.com/davidback/avatars/MikoManju.fbx (missing bones - will give an error in Inspector when applying Humanoid, and an error on export that there is no Chest bone)\r\nhttps://hifi-content.s3.amazonaws.com/davidback/avatars/untiene-jekouson-boy-person.fbx (missing rig - will give an error in Inspector when applying Humanoid, and an error on export that there is no Hips bone)\r\nhttps://hifi-content.s3.amazonaws.com/davidback/avatars/avatar.fbx (missing rig - will give an error about not enough bones in Inspector when applying Humanoid, and an error on export that there is no Hips bone)\r\nhttps://hifi-content.s3.amazonaws.com/davidback/avatars/lego-person.fbx (missing rig - will give an error about not enough bones in Inspector when applying Humanoid, and an error on export that there is no Hips bone)\r\n- Test exporting (import to Unity, change animation type to Humanoid, and Export New Avatar) other random free .fbx avatars from websites like booth.pm, cgtrader.com, clara.io, and turbosquid.com, and verifying them in Interface, and request upload to S3 through me if needed\r\n\r\nAdditional tests:\r\n- Choose an avatar project folder that you exported above, and find a different .fbx file elsewhere that is newer (by modified date)\r\n- Delete the .fbx from your Assets in your Unity project that matches the fbx from the avatar project you chose in the previous step\r\n- Rename the newer .fbx you found above to be the same name as the .fbx you deleted and import it into your Unity Assets\r\n- Select the newly imported avatar and choose Update Existing Avatar to update the avatar.fst from the project you chose above\r\n- Verify a popup is displayed saying Unity fbx is newer than the project fbx and asking if you want to copy the newer one over\r\n- Verify if selecting No that the fbx in your project folder is not changed but the avatar.fst is still changed, but that if performing the update again and select Yes that the fbx in your project folder is replaced with the newer one that you imported to Unity\r\n- Choose an avatar project folder that you exported above, and find a different .fbx file elsewhere that is older (by modified date)\r\n- Delete the .fbx from your Assets in your Unity project that matches the fbx from the avatar project you chose in the previous step\r\n- Rename the newer .fbx you found above to be the same name as the .fbx you deleted and import it into your Unity Assets\r\n- Select the newly imported avatar and choose Update Existing Avatar to update the avatar.fst from the project you chose above\r\n- Verify a popup is displayed saying the project fbx is newer than the Unity fbx and asking if you want to copy the newer one over\r\n- Verify if selecting No that the fbx in your Unity project's Assets folder is unchanged, and the avatar.fst in your exported project folder has it's timestamp is updated but content should remain the same\r\n- Verify if updating avatar again and selecting Yes on the popup this time that the fbx in your Unity project's Assets folder is replaced with the newer one, and the avatar.fst in your exported project folder now matches the avatar.fst that was with in the project folder with the older .fbx file you chose above\r\n\r\nMore additional tests:\r\n- Take any .fbx file and rename the extension to have any amount of capital letters\r\n- Import it into your Unity project and verify the exporter still accepts it as normal","created_at":"2018-12-14T21:10:54Z","updated_at":"2018-12-27T20:21:21Z","closed_at":null,"merged_at":null,"merge_commit_sha":"429ce0ffbc3f7afbfd40cd961d552eddd12ee939","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[{"id":837498945,"node_id":"MDU6TGFiZWw4Mzc0OTg5NDU=","url":"https://api.github.com/repos/highfidelity/hifi/labels/Avatar","name":"Avatar","color":"fcc4dc","default":false},{"id":751510477,"node_id":"MDU6TGFiZWw3NTE1MTA0Nzc=","url":"https://api.github.com/repos/highfidelity/hifi/labels/Create","name":"Create","color":"e288db","default":false},{"id":1119767751,"node_id":"MDU6TGFiZWwxMTE5NzY3NzUx","url":"https://api.github.com/repos/highfidelity/hifi/labels/Development%20Ready","name":"Development Ready","color":"bfdadc","default":false},{"id":278749229,"node_id":"MDU6TGFiZWwyNzg3NDkyMjk=","url":"https://api.github.com/repos/highfidelity/hifi/labels/Feedback%20Welcome","name":"Feedback Welcome","color":"cafc94","default":false},{"id":315234367,"node_id":"MDU6TGFiZWwzMTUyMzQzNjc=","url":"https://api.github.com/repos/highfidelity/hifi/labels/QA%20Rejected%20:sob:","name":"QA Rejected :sob:","color":"e11d21","default":false}],"milestone":{"url":"https://api.github.com/repos/highfidelity/hifi/milestones/38","html_url":"https://github.com/highfidelity/hifi/milestone/38","labels_url":"https://api.github.com/repos/highfidelity/hifi/milestones/38/labels","id":3290838,"node_id":"MDk6TWlsZXN0b25lMzI5MDgzOA==","number":38,"title":"v0.78.0","description":"","creator":{"login":"conklin94122","id":12115653,"node_id":"MDQ6VXNlcjEyMTE1NjUz","avatar_url":"https://avatars2.githubusercontent.com/u/12115653?v=4","gravatar_id":"","url":"https://api.github.com/users/conklin94122","html_url":"https://github.com/conklin94122","followers_url":"https://api.github.com/users/conklin94122/followers","following_url":"https://api.github.com/users/conklin94122/following{/other_user}","gists_url":"https://api.github.com/users/conklin94122/gists{/gist_id}","starred_url":"https://api.github.com/users/conklin94122/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/conklin94122/subscriptions","organizations_url":"https://api.github.com/users/conklin94122/orgs","repos_url":"https://api.github.com/users/conklin94122/repos","events_url":"https://api.github.com/users/conklin94122/events{/privacy}","received_events_url":"https://api.github.com/users/conklin94122/received_events","type":"User","site_admin":false},"open_issues":27,"closed_issues":28,"state":"open","created_at":"2018-04-23T19:27:30Z","updated_at":"2018-12-22T07:22:19Z","due_on":null,"closed_at":null},"commits_url":"https://api.github.com/repos/highfidelity/hifi/pulls/14583/commits","review_comments_url":"https://api.github.com/repos/highfidelity/hifi/pulls/14583/comments","review_comment_url":"https://api.github.com/repos/highfidelity/hifi/pulls/comments{/number}","comments_url":"https://api.github.com/repos/highfidelity/hifi/issues/14583/comments","statuses_url":"https://api.github.com/repos/highfidelity/hifi/statuses/65cc683f800b44afbdf970c9e4af96d6d3ec7714","head":{"label":"dback2:unityAvatarExporter2","ref":"unityAvatarExporter2","sha":"65cc683f800b44afbdf970c9e4af96d6d3ec7714","user":{"login":"dback2","id":31390055,"node_id":"MDQ6VXNlcjMxMzkwMDU1","avatar_url":"https://avatars3.githubusercontent.com/u/31390055?v=4","gravatar_id":"","url":"https://api.github.com/users/dback2","html_url":"https://github.com/dback2","followers_url":"https://api.github.com/users/dback2/followers","following_url":"https://api.github.com/users/dback2/following{/other_user}","gists_url":"https://api.github.com/users/dback2/gists{/gist_id}","starred_url":"https://api.github.com/users/dback2/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dback2/subscriptions","organizations_url":"https://api.github.com/users/dback2/orgs","repos_url":"https://api.github.com/users/dback2/repos","events_url":"https://api.github.com/users/dback2/events{/privacy}","received_events_url":"https://api.github.com/users/dback2/received_events","type":"User","site_admin":false},"repo":{"id":101569298,"node_id":"MDEwOlJlcG9zaXRvcnkxMDE1NjkyOTg=","name":"hifi","full_name":"dback2/hifi","private":false,"owner":{"login":"dback2","id":31390055,"node_id":"MDQ6VXNlcjMxMzkwMDU1","avatar_url":"https://avatars3.githubusercontent.com/u/31390055?v=4","gravatar_id":"","url":"https://api.github.com/users/dback2","html_url":"https://github.com/dback2","followers_url":"https://api.github.com/users/dback2/followers","following_url":"https://api.github.com/users/dback2/following{/other_user}","gists_url":"https://api.github.com/users/dback2/gists{/gist_id}","starred_url":"https://api.github.com/users/dback2/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dback2/subscriptions","organizations_url":"https://api.github.com/users/dback2/orgs","repos_url":"https://api.github.com/users/dback2/repos","events_url":"https://api.github.com/users/dback2/events{/privacy}","received_events_url":"https://api.github.com/users/dback2/received_events","type":"User","site_admin":false},"html_url":"https://github.com/dback2/hifi","description":"Open source client/server software for creating shared VR environments.  Docs at http://wiki.highfidelity.com  We are hiring: http://highfidelity.com/jobs  Also, PT work available at http://worklist.net","fork":true,"url":"https://api.github.com/repos/dback2/hifi","forks_url":"https://api.github.com/repos/dback2/hifi/forks","keys_url":"https://api.github.com/repos/dback2/hifi/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dback2/hifi/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dback2/hifi/teams","hooks_url":"https://api.github.com/repos/dback2/hifi/hooks","issue_events_url":"https://api.github.com/repos/dback2/hifi/issues/events{/number}","events_url":"https://api.github.com/repos/dback2/hifi/events","assignees_url":"https://api.github.com/repos/dback2/hifi/assignees{/user}","branches_url":"https://api.github.com/repos/dback2/hifi/branches{/branch}","tags_url":"https://api.github.com/repos/dback2/hifi/tags","blobs_url":"https://api.github.com/repos/dback2/hifi/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dback2/hifi/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dback2/hifi/git/refs{/sha}","trees_url":"https://api.github.com/repos/dback2/hifi/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dback2/hifi/statuses/{sha}","languages_url":"https://api.github.com/repos/dback2/hifi/languages","stargazers_url":"https://api.github.com/repos/dback2/hifi/stargazers","contributors_url":"https://api.github.com/repos/dback2/hifi/contributors","subscribers_url":"https://api.github.com/repos/dback2/hifi/subscribers","subscription_url":"https://api.github.com/repos/dback2/hifi/subscription","commits_url":"https://api.github.com/repos/dback2/hifi/commits{/sha}","git_commits_url":"https://api.github.com/repos/dback2/hifi/git/commits{/sha}","comments_url":"https://api.github.com/repos/dback2/hifi/comments{/number}","issue_comment_url":"https://api.github.com/repos/dback2/hifi/issues/comments{/number}","contents_url":"https://api.github.com/repos/dback2/hifi/contents/{+path}","compare_url":"https://api.github.com/repos/dback2/hifi/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dback2/hifi/merges","archive_url":"https://api.github.com/repos/dback2/hifi/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dback2/hifi/downloads","issues_url":"https://api.github.com/repos/dback2/hifi/issues{/number}","pulls_url":"https://api.github.com/repos/dback2/hifi/pulls{/number}","milestones_url":"https://api.github.com/repos/dback2/hifi/milestones{/number}","notifications_url":"https://api.github.com/repos/dback2/hifi/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dback2/hifi/labels{/name}","releases_url":"https://api.github.com/repos/dback2/hifi/releases{/id}","deployments_url":"https://api.github.com/repos/dback2/hifi/deployments","created_at":"2017-08-27T17:39:27Z","updated_at":"2018-12-24T17:30:57Z","pushed_at":"2018-12-26T20:17:23Z","git_url":"git://github.com/dback2/hifi.git","ssh_url":"git@github.com:dback2/hifi.git","clone_url":"https://github.com/dback2/hifi.git","svn_url":"https://github.com/dback2/hifi","homepage":"","size":588626,"stargazers_count":0,"watchers_count":0,"language":"C++","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"other","name":"Other","spdx_id":"NOASSERTION","url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"highfidelity:master","ref":"master","sha":"a9f59fae7153e94818e1a566cb092fd3bb56bc2d","user":{"login":"highfidelity","id":1565370,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE1NjUzNzA=","avatar_url":"https://avatars0.githubusercontent.com/u/1565370?v=4","gravatar_id":"","url":"https://api.github.com/users/highfidelity","html_url":"https://github.com/highfidelity","followers_url":"https://api.github.com/users/highfidelity/followers","following_url":"https://api.github.com/users/highfidelity/following{/other_user}","gists_url":"https://api.github.com/users/highfidelity/gists{/gist_id}","starred_url":"https://api.github.com/users/highfidelity/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/highfidelity/subscriptions","organizations_url":"https://api.github.com/users/highfidelity/orgs","repos_url":"https://api.github.com/users/highfidelity/repos","events_url":"https://api.github.com/users/highfidelity/events{/privacy}","received_events_url":"https://api.github.com/users/highfidelity/received_events","type":"Organization","site_admin":false},"repo":{"id":5372872,"node_id":"MDEwOlJlcG9zaXRvcnk1MzcyODcy","name":"hifi","full_name":"highfidelity/hifi","private":false,"owner":{"login":"highfidelity","id":1565370,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE1NjUzNzA=","avatar_url":"https://avatars0.githubusercontent.com/u/1565370?v=4","gravatar_id":"","url":"https://api.github.com/users/highfidelity","html_url":"https://github.com/highfidelity","followers_url":"https://api.github.com/users/highfidelity/followers","following_url":"https://api.github.com/users/highfidelity/following{/other_user}","gists_url":"https://api.github.com/users/highfidelity/gists{/gist_id}","starred_url":"https://api.github.com/users/highfidelity/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/highfidelity/subscriptions","organizations_url":"https://api.github.com/users/highfidelity/orgs","repos_url":"https://api.github.com/users/highfidelity/repos","events_url":"https://api.github.com/users/highfidelity/events{/privacy}","received_events_url":"https://api.github.com/users/highfidelity/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/highfidelity/hifi","description":"Open source client/server software for creating shared VR environments.  Docs at http://docs.highfidelity.com  We are hiring: http://highfidelity.com/jobs  Also, PT work available at http://worklist.net","fork":false,"url":"https://api.github.com/repos/highfidelity/hifi","forks_url":"https://api.github.com/repos/highfidelity/hifi/forks","keys_url":"https://api.github.com/repos/highfidelity/hifi/keys{/key_id}","collaborators_url":"https://api.github.com/repos/highfidelity/hifi/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/highfidelity/hifi/teams","hooks_url":"https://api.github.com/repos/highfidelity/hifi/hooks","issue_events_url":"https://api.github.com/repos/highfidelity/hifi/issues/events{/number}","events_url":"https://api.github.com/repos/highfidelity/hifi/events","assignees_url":"https://api.github.com/repos/highfidelity/hifi/assignees{/user}","branches_url":"https://api.github.com/repos/highfidelity/hifi/branches{/branch}","tags_url":"https://api.github.com/repos/highfidelity/hifi/tags","blobs_url":"https://api.github.com/repos/highfidelity/hifi/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/highfidelity/hifi/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/highfidelity/hifi/git/refs{/sha}","trees_url":"https://api.github.com/repos/highfidelity/hifi/git/trees{/sha}","statuses_url":"https://api.github.com/repos/highfidelity/hifi/statuses/{sha}","languages_url":"https://api.github.com/repos/highfidelity/hifi/languages","stargazers_url":"https://api.github.com/repos/highfidelity/hifi/stargazers","contributors_url":"https://api.github.com/repos/highfidelity/hifi/contributors","subscribers_url":"https://api.github.com/repos/highfidelity/hifi/subscribers","subscription_url":"https://api.github.com/repos/highfidelity/hifi/subscription","commits_url":"https://api.github.com/repos/highfidelity/hifi/commits{/sha}","git_commits_url":"https://api.github.com/repos/highfidelity/hifi/git/commits{/sha}","comments_url":"https://api.github.com/repos/highfidelity/hifi/comments{/number}","issue_comment_url":"https://api.github.com/repos/highfidelity/hifi/issues/comments{/number}","contents_url":"https://api.github.com/repos/highfidelity/hifi/contents/{+path}","compare_url":"https://api.github.com/repos/highfidelity/hifi/compare/{base}...{head}","merges_url":"https://api.github.com/repos/highfidelity/hifi/merges","archive_url":"https://api.github.com/repos/highfidelity/hifi/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/highfidelity/hifi/downloads","issues_url":"https://api.github.com/repos/highfidelity/hifi/issues{/number}","pulls_url":"https://api.github.com/repos/highfidelity/hifi/pulls{/number}","milestones_url":"https://api.github.com/repos/highfidelity/hifi/milestones{/number}","notifications_url":"https://api.github.com/repos/highfidelity/hifi/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/highfidelity/hifi/labels{/name}","releases_url":"https://api.github.com/repos/highfidelity/hifi/releases{/id}","deployments_url":"https://api.github.com/repos/highfidelity/hifi/deployments","created_at":"2012-08-10T18:26:22Z","updated_at":"2018-12-23T05:52:08Z","pushed_at":"2018-12-27T19:38:37Z","git_url":"git://github.com/highfidelity/hifi.git","ssh_url":"git@github.com:highfidelity/hifi.git","clone_url":"https://github.com/highfidelity/hifi.git","svn_url":"https://github.com/highfidelity/hifi","homepage":"","size":587614,"stargazers_count":687,"watchers_count":687,"language":"C++","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":431,"mirror_url":null,"archived":false,"open_issues_count":184,"license":{"key":"other","name":"Other","spdx_id":"NOASSERTION","url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":431,"open_issues":184,"watchers":687,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/highfidelity/hifi/pulls/14583"},"html":{"href":"https://github.com/highfidelity/hifi/pull/14583"},"issue":{"href":"https://api.github.com/repos/highfidelity/hifi/issues/14583"},"comments":{"href":"https://api.github.com/repos/highfidelity/hifi/issues/14583/comments"},"review_comments":{"href":"https://api.github.com/repos/highfidelity/hifi/pulls/14583/comments"},"review_comment":{"href":"https://api.github.com/repos/highfidelity/hifi/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/highfidelity/hifi/pulls/14583/commits"},"statuses":{"href":"https://api.github.com/repos/highfidelity/hifi/statuses/65cc683f800b44afbdf970c9e4af96d6d3ec7714"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"dback2"}}